一、动态代理模式简单理解:
动态代理生成一个对象的代理,这个代理对象拥有和原对象的所有属性和行为,而且还多出另外功能。举个例子:现在有一个对象A1,A1有个方法test(),用动态代理生成对等代理对象A2,A2可以像A1调用test()方法,但是A2会在调用过程插入一些额外的操作。
二、动态代理(JDK)
- 代理对象接口和实现类,下面代码中的TestService和TestServiceImpl
- 代理类,下面代码中的ProxyUtils,需要实现InvocationHandle,实现invoke()方法
- 客户端使用ProxyUtils生成TestService代理对象,调用方法,代码中的test()方法
三、代码实现(推荐在本地跑下,加深理解)
代码实现过程中加入了对SpringAOP的解析,加入了Interceptor拦截器,在代理对象生成类中invoke()方法中实现SpringAOP中的@Before、@After、@AfterReturning、@AfterThrowing注解
- 代理对象接口和实现类TestService和TestServiceImpl
public interface TestService {
public void test();
}
public class TestServiceImpl implements TestService {
@Override
public void test() {
System.out.println("测试开始#############");
}
}
- 代理类ProxyUtils,需要实现InvocationHandle,实现invoke()方法
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* 生成代理对象工具类
* @param <T>
*/
public class ProxyUtils<T> implements InvocationHandler {
private TestService testService;
private Interceptor interceptor;
/**
* 生成代理对象
*
* @param testService
* @param interceptor
* @return
*/
public Object getProxy (TestService testService, Interceptor interceptor) {
this.testService = testService;
this.interceptor = interceptor;
ClassLoader testServiceClassLoader = testService.getClass().getClassLoader();
Class[] testServiceInterfaces = testService.getClass().getInterfaces();
return Proxy.newProxyInstance(testServiceClassLoader, testServiceInterfaces, this);
}
/**
* 执行真实方法步骤:
* 1、先执行before方法
* 2、通过method.invoker执行test()方法
* 3、如果执行test()成功,执行afterReturning方法;否则执行afterThrowing方法
* 4、最终执行after方法
*
* @param proxy
* @param method
* @param args
* @return
* @throws Throwable
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//标记是否出现异常
boolean error = false;
interceptor.before(); //实现SpringAOP中的Before()方法
try{
method.invoke(args);
}
catch (Exception e) {
error = true;
e.printStackTrace();
}
finally {
interceptor.after(); //实现SpringAOP中的After()方法
}
if (error){
interceptor.afterThrowing(); //实现SpringAOP中的AfterThrowing()方法
}
else {
interceptor.afterReturning(); //实现SpringAOP中的AfterReturning()方法
}
return null;
}
}
- 客户端使用ProxyUtils生成TestService代理对象,调用方法,代码中的test()方法
/**
* 动态代理测试客户端
*/
public class Client {
public static void main(String[] args) {
TestService testService = new TestServiceImpl();
Interceptor interceptor = new TestServiceInterceptor();
ProxyUtils proxyUtils = new ProxyUtils();
TestService proxy = (TestService) proxyUtils.getProxy(testService, interceptor);
System.out.println("proxy = " + proxy.getClass().getName());
proxy.test();
}
}
四、源码解析
代理对象生成类中两大关键点:
Proxy.newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h);
生成代理对象的过程如下:
public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h);
{
Objects.requireNonNull(h);
final Class<?> caller = System.getSecurityManager() == null
? null
: Reflection.getCallerClass();
/*
* Look up or generate the designated proxy class and its constructor.
*/
Constructor<?> cons = getProxyConstructor(caller, loader, interfaces);
return newProxyInstance(caller, cons, h);
}
说明:上述代码其实是使用反射机制ClassLoader获取对象的Constructor,然后使用Constructor生成类的对象,对等下面的代码:
public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h);
{
Constructor constructor = testServiceClassLoader.getClass().getConstructor(param);
return constructor.newInstance();
}
返回的代理对象proxy实现了newProxyInstance方法中的参数interfaces接口,并且proxy封装了其他行为,感兴趣的同学可以看看$Proxy0类的实现,当我们执行proxy.test()方法时,首先会经过 $Proxy0调用InvocationHandle中的invoke()方法。