一. 动态代理模式介绍
代理模式(Proxy Pattern):给某⼀个对象提供⼀个代理,并由代理对象控制对原对象的引⽤。代理模式 的英⽂叫做Proxy,它是⼀种对象结构型模式,代理模式分为静态代理和动态代理,我们来介绍动态代理。
举例:
创建⼀个抽象类,Person接⼝,使其拥有⼀个没有返回值的doSomething⽅法。
package com.lagou.dynamicproxy;
public interface Person {
public void doSomething();
}
创建⼀个名为Bob的Person接⼝的实现类,使其实现doSomething⽅法
package com.lagou.dynamicproxy;
public class Bob implements Person {
@Override
public void doSomething() {
System.out.println("Bob doing Something");
}
}
创建JDK动态代理类,使其实现InvocationHandler接⼝。拥有⼀个名为target的变量,并创建 getTa rget获取代理对象⽅法
package com.lagou.dynamicproxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class JDKDynamicProxy implements InvocationHandler {
// 声明被代理的对象
private Person person;
//构造函数
public JDKDynamicProxy(Person person) {
this.person = person;
}
//获取代理对象
public Object getTarget(){
Object proxyInstance = Proxy.newProxyInstance(person.getClass().getClassLoader(), person.getClass().getInterfaces(), this);
return proxyInstance;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("对原方法进行了前置增强");
//原方法执行
Object invoke = method.invoke(person, args);
System.out.println("对原方法进行了后置增强");
return invoke;
}
}
创建JDK动态代理测试类J DKDynamicTest
package com.lagou.dynamicproxy;
public class proxyTest {
public static void main(String[] args) {
System.out.println("不使用代理类,调用doSomething");
Person person = new Bob();
person.doSomething();
System.out.println("--------------------------");
System.out.println("使用代理类,调用doSomething");
Person proxy = (Person) new JDKDynamicProxy(new Bob()).getTarget();
proxy.doSomething();
}
}
二. 模式在Mybatis中实现:
代理模式可以认为是Mybatis的核⼼使⽤的模式,正是由于这个模式,我们只需要编写Mapper.java接 ⼝,不需要实现,由Mybati s后台帮我们完成具体SQL的执⾏。当我们使⽤Configuration的getMapper⽅法时,会调⽤mapperRegistry.getMapper⽅法,⽽该⽅法⼜ 会调⽤ mapperProxyFactory.newInstance(sqlSession)来⽣成⼀个具体的代理:
public class MapperProxyFactory<T> {
private final Class<T> mapperInterface;
private final Map<Method, MapperMethod> methodCache = new
ConcurrentHashMap<Method, MapperMethod>();
public MapperProxyFactory(Class<T> mapperInterface) {
this.mapperInterface = mapperInterface;
}
public Class<T> getMapperInterface() {
return mapperInterface;
}
public Map<Method, MapperMethod> getMethodCache() {
return methodCache;
@SuppressWarnings("unchecked")
protected T newInstance(MapperProxy<T> mapperProxy) {
return (T) Proxy.newProxyInstance(mapperInterface.getClassLoader(), new
Class[] { mapperInterface },
mapperProxy);
}
public T newInstance(SqlSession sqlSession) {
final MapperProxy<T> mapperProxy = new MapperProxy<T>(sqlSession,
mapperInterface, methodCache);
return newInstance(mapperProxy);
}
}
在这⾥,先通过T newInstance(SqlSession sqlSession)⽅法会得到⼀个MapperProxy对象,然后调⽤TnewInstance(MapperProxy mapperProxy)⽣成代理对象然后返回。⽽查看MapperProxy的代码,可以看到如下 内容:
public class MapperProxy<T> implements InvocationHandler, Serializable {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws
Throwable {
try {
if (Object.class.equals(method.getDeclaringClass())) {
return method.invoke(this, args);
} else if (isDefaultMethod(method)) {
return invokeDefaultMethod(proxy, method, args);
}
} catch (Throwable t) {
throw ExceptionUtil.unwrapThrowable(t);
}
final MapperMethod mapperMethod = cachedMapperMethod(method);
return mapperMethod.execute(sqlSession, args);
}
⾮常典型的,该MapperProxy类实现了InvocationHandler接⼝,并且实现了该接⼝的invoke⽅法。通 过这种⽅式,我们只需要编写Mapper.java接⼝类,当真正执⾏⼀个Mapper接⼝的时候,就会转发给 MapperProxy.invoke⽅法,⽽该⽅法则会调⽤后续的sqlSession.cud>executor.execute>prepareStatement 等 ⼀系列⽅法,完成 SQL 的执⾏和返回。