本文思路
- 动态代理在jdk、cglib、spring中如何实现的。
- spring实现动态代理的ProxyFactory详解。
- 从ProxyFactory的使用来了解AOP实现的大概思路。
什么是代理
- 为其他对象提供一种代理以控制对这个对象的访问,增强一个类中的某个方法,对程序进行扩展。
- 常用的实现方式3种:jdk、cglib、spring的ProxyFactory。
如何创建动态代理的方式之JDK
UserService target = new UserService();
// UserInterface接口的代理对象
// 第一个参数为类加载器、第二个参数为代理的接口,第三个参数为代理的具体逻辑
Object proxy = Proxy.newProxyInstance(UserService.class.getClassLoader(), new Class[]{UserInterface.class}, new InvocationHandler() {
/**
* proxy:代理对象
* method:执行的方法
* args:方法参数
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("before...");
Object result = method.invoke(target, args);
System.out.println("after...");
return result;
}
});
UserInterface userService = (UserInterface) proxy;
userService.test();
如何创建动态代理的方式之cglib
UserService target = new UserService();
// 通过cglib技术
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(UserService.class);
// 定义额外逻辑,也就是代理逻辑
enhancer.setCallbacks(new Callback[]{new MethodInterceptor() {
/**
* o:代理对象
* method:被代理对象的方法
* objects:函数调用的参数
* methodProxy:方法的代理
*/
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("before...");
Object result = methodProxy.invoke(target, objects);
System.out.println("after...");
return result;
}
}});
// 动态代理所创建出来的UserService对象
UserService userService = (UserService) enhancer.create();
// 执行这个userService的test方法时,就会额外会执行一些其他逻辑
userService.test();
如何创建动态代理的方式之spring的ProxyFactory
// 得到原始对象
UserService target = new UserService();
// 创建代理工厂
ProxyFactory proxyFactory = new ProxyFactory();
// 指定接口使用jdk的动态代理,不指定接口使用cglib的动态代理
// proxyFactory.setInterfaces(UserInterface.class);
// 设置原始对象
proxyFactory.setTarget(target);
// 添加一个代理逻辑,各种Advice
proxyFactory.addAdvice(new MethodInterceptor() {
@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
System.out.println("before...");
// 执行被代理的方法
Object result = invocation.proceed();
System.out.println("after...");
return result;
}
});
// 得到代理对象,执行
UserInterface userService = (UserInterface) proxyFactory.getProxy();
userService.test();
Advice有哪些
- MethodBeforeAdvice:方法之前执行。可以new MethodBeforeAdvice重写before方法。
- AfterReturningAdvice:方法return后执行。可以new AfterReturningAdvice重写afterReturning方法。
- ThrowsAdvice:方法抛异常后执行。可以new ThrowsAdvice重写afterThrowing方法。afterThrowing的第四个参数是具体的异常,会进行异常的匹配。
- After (finally) advice:方法执行完finally之后执行,这是最后的,比return更后。
- MethodInterceptor:环绕执行这是功能最强大的Advice,可以自定义执行顺序。可以new MethodInterceptor重写invoke方法。
Advisor:在Advice基础上增加了判断!
- Advisor是有一个Pointcut和一个Advice组成。
- 通过Pointcut可以指定要需要被代理的逻辑。比如可以指定那个类的那个方法进行代理。
UserService target = new UserService();
ProxyFactory proxyFactory = new ProxyFactory();
proxyFactory.setTarget(target);
proxyFactory.addAdvisor(new PointcutAdvisor() {
// 进行逻辑匹配
@Override
public Pointcut getPointcut() {
return new StaticMethodMatcherPointcut() {
@Override
public boolean matches(Method method, Class<?> targetClass) {
return method.getName().equals("testAbc");
}
};
}
// 具体的代理逻辑
@Override
public Advice getAdvice() {
return new MethodInterceptor() {
@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
System.out.println("before...");
Object result = invocation.proceed();
System.out.println("after...");
return result;
}
};
}
// 无用的方法,目前看源码只有几个test方法调用了
@Override
public boolean isPerInstance() {
return false;
}
});
UserInterface userService = (UserInterface) proxyFactory.getProxy();
userService.test();
让动态代理的对象成为Bean:ProxyFactoryBean
/**
* 具体代理的Bean
*/
@Bean
public ProxyFactoryBean userService(){
// 定义原始对象
UserService userService = new UserService();
// 得到ProxyFactoryBean对象
ProxyFactoryBean proxyFactoryBean = new ProxyFactoryBean();
// 设置要代理的对象
proxyFactoryBean.setTarget(userService);
// 设置执行哪些BeanName的代理逻辑
proxyFactoryBean.setInterceptorNames("zhangweiAroundAdvise");
// 返回代理对象
return proxyFactoryBean;
}
/**
* 代理的逻辑
*/
@Bean
public MethodInterceptor zhangweiAroundAdvise(){
return new MethodInterceptor() {
@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
System.out.println("before...");
Object result = invocation.proceed();
System.out.println("after...");
return result;
}
};
}
解决让Bean不需要自己指定代理逻辑,降低耦合度:BeanNameAutoProxyCreator
/**
* BeanNameAutoProxyCreator是一个BeanPostProcessor,他在实例化前的时候会执行!
*/
@Bean
public BeanNameAutoProxyCreator beanNameAutoProxyCreator() {
BeanNameAutoProxyCreator beanNameAutoProxyCreator = new BeanNameAutoProxyCreator();
// userSe开头的所有的BeanName,都会执行zhangweiAroundAdvise的代理逻辑
beanNameAutoProxyCreator.setBeanNames("userSe*");
beanNameAutoProxyCreator.setInterceptorNames("zhangweiAroundAdvise");
beanNameAutoProxyCreator.setProxyTargetClass(true);
return beanNameAutoProxyCreator;
}
解决BeanNameAutoProxyCreator只能根据BeanName进行匹配:可以进行方法匹配的DefaultAdvisorAutoProxyCreator
/**
* 定义的一个Advisor。
* 现在的这个逻辑表示只要方法是test,就会进行ZhangweiAfterReturningAdvise代理
*/
@Bean
public DefaultPointcutAdvisor defaultPointcutAdvisor(){
NameMatchMethodPointcut pointcut = new NameMatchMethodPointcut();
pointcut.addMethodName("test");
DefaultPointcutAdvisor defaultPointcutAdvisor = new DefaultPointcutAdvisor();
defaultPointcutAdvisor.setPointcut(pointcut);
defaultPointcutAdvisor.setAdvice(new ZhangweiAfterReturningAdvise());
return defaultPointcutAdvisor;
}
/**
* DefaultAdvisorAutoProxyCreator是一个BeanPostProcessor,他在初始化的时候会执行!
* 他会寻找在spring容器中有哪些Bean的类型是Advisor。匹配容器中的名称是否匹配
* 这个Bean的代码可以写成@Import(DefaultAdvisorAutoProxyCreator.class)
*/
@Bean
public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();
return defaultAdvisorAutoProxyCreator;
}
再次进行简化:@Aspect
@Aspect
@Component
public class ZhangweiAspect {
@Before("execution(public void com.zhangwei.service.UserService.test())")
public void zhangweiBefore(JoinPoint joinPoint) {
System.out.println("zhangweiBefore");
}
}
结束语
- 获取更多本文的前置知识文章,以及新的有价值的文章,让我们一起成为架构师!
- 关注公众号,可以让你对MySQL、并发编程、spring源码有深入的了解!
- 关注公众号,后续持续高效的学习JVM!
- 这个公众号,无广告!!!每日更新!!!