本文共 6744 字,大约阅读时间需要 22 分钟。
Advice,我们通常都会把他翻译为通知,其实很不好理解,其实他还有另外一个意思,就是“建议”,我觉得把Advice理解为“建议”会更好。
比如,我们已经完成了一个功能,这时客户跟我们说,我建议在这个功能之前可以再增加一些逻辑,再之后再增加一些逻辑。
在Spring中,Advice分为:
在利用Spring AOP去生成一个代理对象时,我们可以设置这个代理对象的Advice。
而对于Advice来说,它只表示了“建议”,它没有表示这个“建议”可以用在哪些方面。
就好比,我们已经完成了一个功能,客户给这个功能提了一个建议,但是这个建议也许也能用到其他功能上。
这时,就出现了Advisor,表示一个Advice可以应用在哪些地方,而“哪些地方”就是Pointcut(切点)。
切点,表示我想让哪些地方加上我的代理逻辑。
比如某个方法,
比如某些方法,
比如某些方法名前缀为“find”的方法,
比如某个类下的所有方法,等等。
在Pointcut中,有一个MethodMatcher,表示方法匹配器。
定义一个MyAdvisor
public class MyAdvisor implements PointcutAdvisor { @Override public Pointcut getPointcut() { NameMatchMethodPointcut methodPointcut = new NameMatchMethodPointcut(); methodPointcut.addMethodName("test"); return methodPointcut; } @Override public Advice getAdvice() { MethodBeforeAdvice methodBeforeAdvice = new MethodBeforeAdvice() { @Override public void before(Method method, Object[] args, Object target) throws Throwable { System.out.println("执行方法前"+method.getName()); } }; return methodBeforeAdvice; } @Override public boolean isPerInstance() { return false; }}
定义一个UserService
public class UserService { public void test() { System.out.println("111"); }}
ProxyFactory factory = new ProxyFactory();factory.setTarget(new UserService());factory.addAdvisor(new MyAdvisor());UserService userService = (UserService) factory.getProxy();userService.test();
ProxyFactory就是一个代理对象生产工厂,在生成代理对象之前需要对代理工厂进行配置。
ProxyFactory在生成代理对象之前需要决定到底是使用JDK动态代理还是CGLIB技术:
// config就是ProxyFactory对象// optimize为true,或proxyTargetClass为true,或用户没有给ProxyFactory对象添加interfaceif (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) { Class targetClass = config.getTargetClass(); if (targetClass == null) { throw new AopConfigException("TargetSource cannot determine target class: " + "Either an interface or a target is required for proxy creation."); } // targetClass是接口,直接使用Jdk动态代理 if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) { return new JdkDynamicAopProxy(config); } // 使用Cglib return new ObjenesisCglibAopProxy(config);}else { // 使用Jdk动态代理 return new JdkDynamicAopProxy(config);}
执行过程主要就看DynamicAdvisedInterceptor中的实现,执行逻辑和JdkDynamicAopProxy中是一样的。
"自动代理"表示,只需要在Spring中添加某个Bean,这个Bean是一个BeanPostProcessor,那么Spring在每创建一个Bean时,都会经过这个BeanPostProcessor的判断,去判断当前正在创建的这个Bean是不是需要进行AOP。
我们可以在项目中定义很多个Advisor,定义方式有两种:
在创建某个Bean时,会根据当前这个Bean的信息,比如对应的类,以及当前Bean中的方法信息,去和定义的所有Advisor进行匹配,如果匹配到了其中某些Advisor,那么就会把这些Advisor给找出来,并且添加到ProxyFactory中去,在利用ProxyFactory去生成代理对象
@Beanpublic BeanNameAutoProxyCreator creator(){ BeanNameAutoProxyCreator beanNameAutoProxyCreator = new BeanNameAutoProxyCreator(); beanNameAutoProxyCreator.setBeanNames("userService"); beanNameAutoProxyCreator.setInterceptorNames("myAdvisor"); return beanNameAutoProxyCreator;}
定义的这个bean,相当于一个“自动代理”器,有了这个Bean之后,可以自动的对setBeanNames中所对应的bean进行代理,代理逻辑为所设置的interceptorNames
DefaultAdvisorAutoProxyCreator这个更加强大,只要添加了这个Bean,它就会自动识别所有的Advisor中的PointCut进行代理
AbstractAutoProxyCreator实现了SmartInstantiationAwareBeanPostProcessor接口,是一个BeanPostProcessor
AbstractAdvisorAutoProxyCreator继承了AbstractAutoProxyCreator,AbstractAdvisorAutoProxyCreator中实现了getAdvicesAndAdvisorsForBean()方法,实现逻辑为:
这个注解主要是添加了一个AnnotationAwareAspectJAutoProxyCreator类型的BeanDefinition
AspectJAwareAdvisorAutoProxyCreator继承了AbstractAdvisorAutoProxyCreator,重写了shouldSkip(Class<?> beanClass, String beanName)方法,表示某个bean需不需要进行AOP,在shouldSkip()方法中:
AnnotationAwareAspectJAutoProxyCreator继承了AspectJAwareAdvisorAutoProxyCreator,重写了findCandidateAdvisors()方法,它即可以找到Advisor类型的bean,也能把所有@Aspect注解标注的类扫描出来并生成Advisor
转载地址:http://jdbnb.baihongyu.com/