AOP中的几个概念
Advisor 和 Advice
Advice
我们通常都会把他翻译为通知,其实很不好理解,其实他还有另外一个意思,就是“建议”,我觉得把Advice理解为“建议”会更好。就是代理的逻辑。
比如,我们已经完成了一个功能,这时客户跟我们说,我建议在这个功能之前可以再增加一些逻辑,再之后再增加一些逻辑。
在Spring中,Advice分为:
- 前置Advice:MethodBeforeAdvice
- 后置Advice:AfterReturningAdvice
- 环绕Advice:MethodInterceptor
- 异常Advice:ThrowsAdvice
在利用Spring AOP去生成一个代理对象时,我们可以设置这个代理对象的Advice。
而对于Advice来说,它只表示了“建议”,它没有表示这个“建议”可以用在哪些方面。
就好比,我们已经完成了一个功能,客户给这个功能提了一个建议,但是这个建议也许也能用到其他功能上。
这时,就出现了Advisor,表示一个Advice可以应用在哪些地方,而“哪些地方”就是Pointcut(切点)。
Pointcut
切点,表示我想让哪些地方加上我的代理逻辑。
比如某个方法,
比如某些方法,
比如某些方法名前缀为“find”的方法,
比如某个类下的所有方法,等等。
在Pointcut中,有一个MethodMatcher,表示方法匹配器。
Advisor
就等于Pointcut+Advice.
Spring中的AOP代理类是通过一个ProxyFactory类来实现的。
先简单介绍下这个类的简单用法:
public static void main(String[] args) {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);
UserInterface userService = (UserInterface) applicationContext.getBean("userService");
userService.test();
// testAop();
}
public static void testAop(){
ProxyFactory proxyFactory = new ProxyFactory();
// 设置目标对象
proxyFactory.setTarget(new UserService());
// proxyFactory.setTargetClass(UserService.class);
proxyFactory.addInterface(UserInterface.class); // 表示想使用jdk动态代理
proxyFactory.getTargetSource();
// 生成代理逻辑 ,注意这里添加的只是一个Advice,底层是要封装成一个Advisor来交给代理工厂管理的。
// 这里添加了Advice,底层使用 DefaultPointcutAdvisor 封装,它的PointCut是Pointcut.TRUE 表示匹配所有类的切点的都使用
proxyFactory.addAdvice(new MethodBeforeAdvice() {
@Override
public void before(Method method, Object[] args, Object target) throws Throwable {
System.out.println(method.getName()+"方法调用之前执行的代理逻辑");
}
});
// UserService 实现了 UserInterface 接口
// 生成代理对象 UserService 是个实现类,如果是cglib动态代理,代理类是可以强转成它的,但是如果是jdk动态代理,它就不能强转成UserService类
// 因为cglib是基于子类来实现的,jdk动态代理是基于接口实现类来的
// UserService proxy = (UserService) proxyFactory.getProxy();
// jdk动态代理 {代理类 extends Proxy implement 目标接口}
UserInterface proxy = (UserInterface) proxyFactory.getProxy();
proxy.test();
}
1:上面ProxyFactory的构造方法,会把传进去的目标对象封装成一个TargetSource
public void setTarget(Object target) { setTargetSource(new SingletonTargetSource(target)); }
2: 还有一种设置目标对象的方式,就是:proxyFactory.setTargetClass(UserService.class);
public void setTargetClass(@Nullable Class<?> targetClass) { this.targetSource = EmptyTargetSource.forClass(targetClass); }
两种设置方式得到的 this.targetSource 这个属性是不一样的,
一个是: EmptyTargetSource ,一个是 SingletonTargetSource,他们都继承了 TargetSource,但是对于SingletonTargetSource来说,它的target属性,和getTargetClass都是可以得到值的。
但是对于EmptyTargetSource 来说,它只有getTargetClass能得到值,因为是直接赋值的,它的getTarget是直接返回null的。
上面代理工厂ProxyFactory#getProxy得到一个代理类中,会先得到一个具体的代理工厂,有两种jdk的代理工厂和cglib的代理工厂。
public Object getProxy() { return createAopProxy().getProxy(); }
protected final synchronized AopProxy createAopProxy() { if (!this.active) { activate(); } // 默认用的就是DefaultAopProxyFactory return getAopProxyFactory().createAopProxy(this); }
DefaultAopProxyFactory#createAopProxy 中:
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException { // Spring到底何时使用cglib,何时使用jdk动态代理 // 如果设置的targetClass是一个接口,会使用jdk动态代理 // 默认情况下(optimize为false, isProxyTargetClass为false), ProxyFactory添加了接口时,也会使用jdk动态代理 // 这个config 就是外面的按个ProxyFactory 它的父类 extends ProxyConfig implements Advised // config.isOptimize() 跟CGlib优化 可以在外面设置 ,默认为false // config.isProxyTargetClass() 默认为false ,是否使用cglib, 这个属性也可以通过 @EnableAspectJAutoProxy 注解设置,注解属性里面也有这个属性 // hasNoUserSuppliedProxyInterfaces 是不是没有用户提供的代理接口 :这个指的是 可以通过proxyFactory.addInterface() 添加接口 // 添加之后 hasNoUserSuppliedProxyInterfaces(config)会判断 是否进入下面的逻辑 if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) { // 这个 getTargetClass() 就是外面setTarget或者 setTargetClass 之后可以得到的值 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的动态代理 ,如果外面是通过setTarget赋值的,那么targetClass肯定不是接口,因为参数是个对象 // setTargetClass 设置的可以是个接口 if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) { // 返回jdk的代理工厂 return new JdkDynamicAopProxy(config); } // 返回cglib的代理工厂 return new ObjenesisCglibAopProxy(config); } else { return new JdkDynamicAopProxy(config); } }
而一般在我们使用过程中,如果只开启了注解:@EnableAspectJAutoProxy ,Spring会根据类是否有接口来判断是否用jdk动态代理还是cglib动态代理。如果在 @EnableAspectJAutoProxy(proxyTargetClass = true) 加上属性,则就会都优先使用cglib的动态代理。
上面分析了得到代理工厂,代理工厂得到得到代理类是 getProxy()。代理工厂两个: JdkDynamicAopProxy,ObjenesisCglibAopProxy。
JdkDynamicAopProxy#getProxy()
jdk动态代理生成的代理类是实现一些指定接口的代理类,实现那些接口是: AopProxyUtils.completeProxiedInterfaces(this.advised, true); 查找。
public Object getProxy(@Nullable ClassLoader classLoader) { // this.advised 就是ProxyFactory对象 if (logger.isTraceEnabled()) { logger.trace("Creating JDK dynamic proxy: " + this.advised.getTargetSource()); } // 获取生成代理对象所需要实现的接口 // 如果通过指定了 proxyFactory.addInterface 指定了接口,则算上一个,如果没有指定则看targetClass 是不是接口 如果是的话这个接口算上一个 // 最后还会加上Spring 自带的三个接口 SpringProxy(只是标记接口,标记是个AOP代理类)、Advised(可以管理AOP 的通知,在使用代理类的时候可以强转为它 进行管理)、 // DecoratingProxy Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true); // 判断这些接口中有没有定义equals方法,hashcode方法 findDefinedEqualsAndHashCodeMethods(proxiedInterfaces); // 针对所指定的接口生成代理对象,包括用户所添加的接口以及SpringProxy、Advised、DecoratingProxy // 所以生成的代理对象可以强制转换成任意一个接口类型 // 用的也是JDK中的代理方式, 传入了this对象,也就是JdkDynamicAopProxy implements AopProxy, InvocationHandler // 调用代理类方法的时候,就会走 下面的invoke方法 return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this); }
先把原理图放出来:
Spring中创建AOP代理的方式
上面创建代理类举例子是通过ProxyFactory来的,在spring中是底层才用到这个类,在spring中有几种实用的创建AOP代理的方式。
1:通过 BeanNameAutoProxyCreator 这个后置处理器,进行自动代理。
看到它继承了 AbstractAutoProxyCreator,父类实现了 SmartInstantiationAwareBeanPostProcessor后置处理器,里面肯定有个postProcessBeforeInstantiation,postProcessAfterInitialization。
在postProcessBeforeInstantiation逻辑中会有判断是否需要提前创建代理对象的逻辑。还会判断是否要跳过当前bean的代理逻辑的处理: this.advisedBeans.put(cacheKey, Boolean.FALSE);
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) { Object cacheKey = getCacheKey(beanClass, beanName); if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) { // advisedBeans中存的是当前这个bean需不需要代理 if (this.advisedBeans.containsKey(cacheKey)) { return null; } // 当前bean是不是不需要进行代理 if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) { this.advisedBeans.put(cacheKey, Boolean.FALSE); return null; } } // 查看是否需要提前生成代理对象 // Create proxy here if we have a custom TargetSource. // Suppresses unnecessary default instantiation of the target bean: // The TargetSource will handle target instances in a custom fashion. // 判断当前beanClass和beanName是否会生成一个TargetSource,如果生成了,就进行代理 TargetSource targetSource = getCustomTargetSource(beanClass, beanName); if (targetSource != null) { if (StringUtils.hasLength(beanName)) { this.targetSourcedBeans.add(beanName); } Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource); // 创建一个代理对象 Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource); this.proxyTypes.put(cacheKey, proxy.getClass()); return proxy; } return null; }
一般的AOP代理逻辑处理是在postProcessAfterInitialization中的
// 正常情况进行AOP的地方 public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) { if (bean != null) { Object cacheKey = getCacheKey(bean.getClass(), beanName); // earlyProxyReferences中存的是哪些提前进行了AOP的bean,beanName:AOP之前的对象 // 注意earlyProxyReferences中并没有存AOP之后的代理对象 BeanPostProcessor if (this.earlyProxyReferences.remove(cacheKey) != bean) { // 没有提前进行过AOP,则进行AOP return wrapIfNecessary(bean, beanName, cacheKey); } } // 为什么不返回代理对象呢? return bean; // }
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) { // 在当前targetSourcedBeans中存在的bean,表示在实例化之前就产生了代理对象 if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) { return bean; } // 当前这个bean不用被代理 this.advisedBean 存储一个bean需不需要被代理 if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) { return bean; } // 先判断当前bean是不是要进行AOP,比如当前bean的类型是Pointcut、Advice、Advisor AopInfrastructureBean 那就不需要进行AOP // shouldSkip 给子类来实现判断是否需要进行AOP代理 if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) { this.advisedBeans.put(cacheKey, Boolean.FALSE); return bean; } // Create proxy if we have advice. // 这么说不对: 获取当前beanClass所匹配的advisors(PointCut+Advice) 或者Advice // 也是由子类来实现逻辑的 BeanNameAutoProxyCreator // 只是返回一个标记 DO_NOT_PROXY、PROXY_WITHOUT_ADDITIONAL_INTERCEPTORS 看是否需要进行AOP代理 Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null); // 如果匹配的advisors不等于null,那么则进行代理,并返回代理对象 if (specificInterceptors != DO_NOT_PROXY) { this.advisedBeans.put(cacheKey, Boolean.TRUE); // 基于bean对象和Advisor创建代理对象 Object proxy = createProxy( bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean)); // 存一个代理对象的类型 this.proxyTypes.put(cacheKey, proxy.getClass()); return proxy; } this.advisedBeans.put(cacheKey, Boolean.FALSE); return bean; }
1.1:定义 BeanNameAutoProxyCreator
// 自动代理 BeanPost @Bean public BeanNameAutoProxyCreator creator(){ // BeanPostProcessor BeanNameAutoProxyCreator beanNameAutoProxyCreator = new BeanNameAutoProxyCreator(); // 设置要目标bean的beanName,可以配置多个 beanNameAutoProxyCreator.setBeanNames("userService"); // bean==>AOP // 设置拦截器名称,其实就是Advisor= PointCut+Advice beanNameAutoProxyCreator.setInterceptorNames("myAdvisor"); return beanNameAutoProxyCreator; }
1.2: 定义Advisor
@Component public class MyAdvisor implements PointcutAdvisor { @Override public Pointcut getPointcut() { // 设置切点信息,通过方法的名字匹配切点 NameMatchMethodPointcut pointcut = new NameMatchMethodPointcut(); // 设置了切点为 方法名是test的方法 pointcut.addMethodName("test"); return pointcut; } @Override public Advice getAdvice() { // 设置Advice 增强的逻辑 return new MethodBeforeAdvice() { @Override public void before(Method method, Object[] args, Object target) throws Throwable { System.out.println("Myadvisor方法执行前"+target.getClass().getName()); } }; } @Override public boolean isPerInstance() { return false; } }
上面的方式配置的AOP逻辑实现了。
2:还有一种通过 DefaultAdvisorAutoProxyCreator来进行AOP逻辑查找匹配的方式。
@Bean public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator(){ DefaultAdvisorAutoProxyCreator creator = new DefaultAdvisorAutoProxyCreator(); return creator; }
DefaultAdvisorAutoProxyCreator 是找Advisor类型的bean,然后进行匹配。就是上面自定义的MyAdvisor。
这个Bean可以替换掉上面的那个BeanNameAutoProxyCreator。但是这种方式也不方便,因为定义Advisor不够灵活,配置比较麻烦。
3:使用注解,这种方式比较常用。@EnableAspectJAutoProxy
这个注解有 proxyTargetClass 属性默认false(如果为true表示要使用cglib的动态代理),exposeProxy 属性默认为false。
Advisor是通过如下方式:
@Component @Aspect public class TestAspect { @Before("execution(public void com.luban.service.UserService.test())") public void before(){ System.out.println("注解前置方法执行"); } }
在配置类上加了这个注解之后,这个注解会引入一个类:AspectJAutoProxyRegistrar。和上面的方式相比:
AspectJAutoProxyRegistrar 继承 ImportBeanDefinitionRegistrar ,具有注册beanDefinition的功能。就是 registerBeanDefinitions方法:注册一个AnnotationAwareAspectJAutoProxyCreator 类。
public void registerBeanDefinitions( AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) { // 注册一个 AnnotationAwareAspectJAutoProxyCreator 的bean AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry); AnnotationAttributes enableAspectJAutoProxy = AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class); if (enableAspectJAutoProxy != null) { if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) { AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry); } if (enableAspectJAutoProxy.getBoolean("exposeProxy")) { AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry); } } }
AnnotationAwareAspectJAutoProxyCreator 的继承结构如上图,它不仅可以找到Advisor类型的bean,还可以找@Aspect标注的bean。
这种注解方式的执行流程按照上面的继承关系重新整理一下如下:
1:AbstractAutoProxyCreator
是个bean的后置处理器,在某个bean的创建过程中,会执行它里面的postProcessBeforeInstantiation,postProcessAfterInitialization
AbstractAutoProxyCreator#postProcessBeforeInstantiation
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) { Object cacheKey = getCacheKey(beanClass, beanName); if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) { // advisedBeans中存的是当前这个bean需不需要代理 if (this.advisedBeans.containsKey(cacheKey)) { return null; } // 当前bean是不是不需要进行代理 里面的两个方法都可以被子类实现,作为自己不同场景下的判断 if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) { this.advisedBeans.put(cacheKey, Boolean.FALSE); return null; } } // 查看是否需要提前生成代理对象 // Create proxy here if we have a custom TargetSource. // Suppresses unnecessary default instantiation of the target bean: // The TargetSource will handle target instances in a custom fashion. // 判断当前beanClass和beanName是否会生成一个TargetSource,如果生成了,就进行代理 TargetSource targetSource = getCustomTargetSource(beanClass, beanName); if (targetSource != null) { if (StringUtils.hasLength(beanName)) { this.targetSourcedBeans.add(beanName); } Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource); // 创建一个代理对象 Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource); this.proxyTypes.put(cacheKey, proxy.getClass()); return proxy; } return null; }
上面有两个方法isInfrastructureClass,shouldSkip可以由子类来判断一个bean要不要进行代理。
AnnotationAwareAspectJAutoProxyCreator #isInfrastructureClass
protected boolean isInfrastructureClass(Class<?> beanClass) { // Previously we setProxyTargetClass(true) in the constructor, but that has too // broad an impact. Instead we now override isInfrastructureClass to avoid proxying // aspects. I'm not entirely happy with that as there is no good reason not // to advise aspects, except that it causes advice invocation to go through a // proxy, and if the aspect implements e.g the Ordered interface it will be // proxied by that interface and fail at runtime as the advice method is not // defined on the interface. We could potentially relax the restriction about // not advising aspects in the future. // 调用父类的过滤方法,如果父类没有过滤掉,调用自己增加的增加的过滤方法(过滤掉@Aspect注解标注的bean,因为这是作为Advisor集合的bean) return (super.isInfrastructureClass(beanClass) || (this.aspectJAdvisorFactory != null && this.aspectJAdvisorFactory.isAspect(beanClass))); }
父类中AbstractAutoProxyCreator#isInfrastructureClass
protected boolean isInfrastructureClass(Class<?> beanClass) { // 过滤掉一些 和AOP相关的bean boolean retVal = Advice.class.isAssignableFrom(beanClass) || Pointcut.class.isAssignableFrom(beanClass) || Advisor.class.isAssignableFrom(beanClass) || AopInfrastructureBean.class.isAssignableFrom(beanClass); if (retVal && logger.isTraceEnabled()) { logger.trace("Did not attempt to auto-proxy infrastructure class [" + beanClass.getName() + "]"); } return retVal; }
AspectJAwareAdvisorAutoProxyCreator#shouldSkip
protected boolean shouldSkip(Class<?> beanClass, String beanName) { // TODO: Consider optimization by caching the list of the aspect names // 得到类型为Advisor的bean,以及被@Aspect注解修饰了的类中所定义的@Before等 List<Advisor> candidateAdvisors = findCandidateAdvisors(); // 如果当前beanName是AspectJPointcutAdvisor,那么则跳过 for (Advisor advisor : candidateAdvisors) { if (advisor instanceof AspectJPointcutAdvisor && ((AspectJPointcutAdvisor) advisor).getAspectName().equals(beanName)) { return true; } } // 调用父类的的shouldSkip 方法 return super.shouldSkip(beanClass, beanName); }
父类中AbstractAutoProxyCreator#shouldSkip
protected boolean shouldSkip(Class<?> beanClass, String beanName) { return AutoProxyUtils.isOriginalInstance(beanName, beanClass); }
static boolean isOriginalInstance(String beanName, Class<?> beanClass) { if (!StringUtils.hasLength(beanName) || beanName.length() != beanClass.getName().length() + AutowireCapableBeanFactory.ORIGINAL_INSTANCE_SUFFIX.length()) { return false; } return (beanName.startsWith(beanClass.getName()) && beanName.endsWith(AutowireCapableBeanFactory.ORIGINAL_INSTANCE_SUFFIX)); }
在 AspectJAwareAdvisorAutoProxyCreator#shouldSkip中有一个 findCandidateAdvisors 的方法,找到所有候选者Advisor
它由子类重写了,AnnotationAwareAspectJAutoProxyCreator#findCandidateAdvisors如下
protected List<Advisor> findCandidateAdvisors() { // Add all the Spring advisors found according to superclass rules. // 先去调用父类的 findCandidateAdvisors 方法 // Advisor=Pointcut+Advice (切点加建议) ,获得到所有Advisor类型的bean List<Advisor> advisors = super.findCandidateAdvisors(); // Build Advisors for all AspectJ aspects in the bean factory. // 找的是通过AspectJ的方式定义的Advisor if (this.aspectJAdvisorsBuilder != null) { advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors()); } return advisors; }
假如上面实例化之前的那个方法没有进行Aop代理,那么正常AOP代理对象是在postProcessAfterInitialization中产生的。
AbstractAutoProxyCreator#postProcessAfterInitialization
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) { if (bean != null) { Object cacheKey = getCacheKey(bean.getClass(), beanName); // earlyProxyReferences中存的是哪些提前进行了AOP的bean,beanName:AOP之前的对象 // 注意earlyProxyReferences中并没有存AOP之后的代理对象 BeanPostProcessor if (this.earlyProxyReferences.remove(cacheKey) != bean) { // 没有提前进行过AOP,则进行AOP return wrapIfNecessary(bean, beanName, cacheKey); } } // 为什么不返回代理对象呢? return bean; // }
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) { // 在当前targetSourcedBeans中存在的bean,表示在实例化之前就产生了代理对象 if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) { return bean; } // 当前这个bean不用被代理 this.advisedBean 存储一个bean需不需要被代理 if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) { return bean; } // 先判断当前bean是不是要进行AOP,比如当前bean的类型是Pointcut、Advice、Advisor AopInfrastructureBean 那就不需要进行AOP // shouldSkip 给子类来实现判断是否需要进行AOP代理 if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) { this.advisedBeans.put(cacheKey, Boolean.FALSE); return bean; } // Create proxy if we have advice. // 这么说不对: 获取当前beanClass所匹配的advisors(PointCut+Advice) 或者Advice // 也是由子类来实现逻辑的 BeanNameAutoProxyCreator // 只是返回一个标记 DO_NOT_PROXY、PROXY_WITHOUT_ADDITIONAL_INTERCEPTORS 看是否需要进行AOP代理 Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null); // 如果匹配的advisors不等于null,那么则进行代理,并返回代理对象 if (specificInterceptors != DO_NOT_PROXY) { this.advisedBeans.put(cacheKey, Boolean.TRUE); // 基于bean对象和Advisor创建代理对象 Object proxy = createProxy( bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean)); // 存一个代理对象的类型 this.proxyTypes.put(cacheKey, proxy.getClass()); return proxy; } this.advisedBeans.put(cacheKey, Boolean.FALSE); return bean; }
AbstractAdvisorAutoProxyCreator#getAdvicesAndAdvisorsForBean
protected Object[] getAdvicesAndAdvisorsForBean( Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) { // 针对当前bean查找合格的Advisor List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName); if (advisors.isEmpty()) { return DO_NOT_PROXY; } return advisors.toArray(); }
// 查找合格的Advisor(和beanClass匹配) protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) { // 得到所有的Advisor List<Advisor> candidateAdvisors = findCandidateAdvisors(); // 进行筛选 筛选和beanClass匹配的Advisor List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName); // 提供给子类去额外的添加advisor extendAdvisors(eligibleAdvisors); if (!eligibleAdvisors.isEmpty()) { // 按order进行排序 eligibleAdvisors = sortAdvisors(eligibleAdvisors); } // 返回匹配的Advisor return eligibleAdvisors; }
protected List<Advisor> findCandidateAdvisors() { // Add all the Spring advisors found according to superclass rules. // 先去调用父类的 findCandidateAdvisors 方法 // Advisor=Pointcut+Advice (切点加建议) ,获得到所有Advisor类型的bean List<Advisor> advisors = super.findCandidateAdvisors(); // Build Advisors for all AspectJ aspects in the bean factory. // 找的是通过AspectJ的方式定义的Advisor 找到@Aspect注解标注的类 if (this.aspectJAdvisorsBuilder != null) { advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors()); } return advisors; }
进行创建代理的逻辑:createProxy
protected Object createProxy(Class<?> beanClass, @Nullable String beanName, @Nullable Object[] specificInterceptors, TargetSource targetSource) { if (this.beanFactory instanceof ConfigurableListableBeanFactory) { AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass); } ProxyFactory proxyFactory = new ProxyFactory(); proxyFactory.copyFrom(this); // 复制配置参数 // 是否指定了必须用cglib进行代理 if (!proxyFactory.isProxyTargetClass()) { // 如果没有指定,那么则判断是不是应该进行cglib代理(判断BeanDefinition中是否指定了要用cglib) if (shouldProxyTargetClass(beanClass, beanName)) { proxyFactory.setProxyTargetClass(true); } else { // 是否进行jdk动态代理,如果当前beanClass实现了某个接口,那么则会使用JDK动态代理 evaluateProxyInterfaces(beanClass, proxyFactory); // 判断beanClass有没有实现接口 } } // 将commonInterceptors和specificInterceptors整合再一起 Advisor[] advisors = buildAdvisors(beanName, specificInterceptors); proxyFactory.addAdvisors(advisors); // 向ProxyFactory中添加advisor proxyFactory.setTargetSource(targetSource); // 被代理的对象 customizeProxyFactory(proxyFactory); proxyFactory.setFrozen(this.freezeProxy); // if (advisorsPreFiltered()) { proxyFactory.setPreFiltered(true); } // 生成代理对象 return proxyFactory.getProxy(getProxyClassLoader()); }
首先创建ProxyFactory对象,开头已经介绍过这个类了。
public void copyFrom(ProxyConfig other) { Assert.notNull(other, "Other ProxyConfig object must not be null"); this.proxyTargetClass = other.proxyTargetClass; // 是否开启cglib this.optimize = other.optimize; this.exposeProxy = other.exposeProxy; // 是否将生成的代理对象设置到AopContext中去,后面可以通过AopContext.currentProxy()拿到 this.frozen = other.frozen; this.opaque = other.opaque; }
从上面可以看出,是否要用cglib进行代理,不止是看目标对象是否实现了某个接口,还和proxyTargetClass属性有关,这个属性在 @EnableAspectJAutoProxy中有设置,注入AnnotationAwareAspectJAutoProxyCreator的时候赋值进去的,然而看上面的逻辑,就算是
没有设置,还会判断当前bean对应的BeanDefinition中是否有设置一个名为:org.springframework.aop.framework.autoproxy.AutoProxyUtils.preserveTargetClass=true的属性,如果有的话也会设置为true。
getProxy中,会先判断使用JDK代理工厂还是使用cglib的代理工厂
public Object getProxy(@Nullable ClassLoader classLoader) { // 根据不同的情况得到不同的动态代理工厂,cglib或jdk动态代理 return createAopProxy().getProxy(classLoader); }
protected final synchronized AopProxy createAopProxy() { if (!this.active) { activate(); } // 默认用的就是DefaultAopProxyFactory return getAopProxyFactory().createAopProxy(this); }
AopProxy有两种,一种是JdkDynamicAopProxy,一种是CglibAopProxy
JdkDynamicAopProxy#getProxy
public Object getProxy(@Nullable ClassLoader classLoader) { // this.advised 就是ProxyFactory对象 if (logger.isTraceEnabled()) { logger.trace("Creating JDK dynamic proxy: " + this.advised.getTargetSource()); } // 获取生成代理对象所需要实现的接口 // 如果通过指定了 proxyFactory.addInterface 指定了接口,则算上一个,如果没有指定则看targetClass 是不是接口 如果是的话这个接口算上一个 // 最后还会加上Spring 自带的三个接口 SpringProxy(只是标记接口,标记是个AOP代理类)、Advised(可以管理AOP 的通知,在使用代理类的时候可以强转为它 进行管理)、 // DecoratingProxy Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true); // 判断这些接口中有没有定义equals方法,hashcode方法 findDefinedEqualsAndHashCodeMethods(proxiedInterfaces); // 针对所指定的接口生成代理对象,包括用户所添加的接口以及SpringProxy、Advised、DecoratingProxy // 所以生成的代理对象可以强制转换成任意一个接口类型 // 用的也是JDK中的代理方式, 传入了this对象,也就是JdkDynamicAopProxy implements AopProxy, InvocationHandler // 调用代理类方法的时候,就会走 下面的invoke方法 return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this); }
JdkDynamicAopProxy 本身是一个InvocationHandler,所以当调用目标对象的方法时就会执行JdkDynamicAopProxy#invoke方法。
里面主要的逻辑如下:
上面的 this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);,会得到那些在@Aspect中定义的Advice。这些Advice根据@Before,@After等等的不同,分为AspectJAroundAdvice等等。
然后把这个执行链,还有代理对象,目标对象封装成 ReflectiveMethodInvocation,然后执行其proceed方法,这个方法是个递归调用。
public Object proceed() throws Throwable { // We start with an index of -1 and increment early. // this.currentInterceptorIndex 默认=-1 if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
// 最后执行method本身的逻辑 return invokeJoinpoint(); } Object interceptorOrInterceptionAdvice = this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex); if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) { // Evaluate dynamic method matcher here: static part will already have // been evaluated and found to match. InterceptorAndDynamicMethodMatcher dm = (InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice; Class<?> targetClass = (this.targetClass != null ? this.targetClass : this.method.getDeclaringClass()); if (dm.methodMatcher.matches(this.method, targetClass, this.arguments)) { return dm.interceptor.invoke(this); } else { // Dynamic matching failed. // Skip this interceptor and invoke the next in the chain. return proceed(); } } else { // It's an interceptor, so we just invoke it: The pointcut will have // been evaluated statically before this object was constructed. // 调用 AspectJAroundAdvice,AspectJAfterReturningAdvice 等 return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this); } }
以MethodBeforeAdviceInterceptor#invoke为例子
public Object invoke(MethodInvocation mi) throws Throwable {
// 先执行@Aspect中@Before标注的方法 this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis());
// 然后继续调用下一个Advice方法 return mi.proceed(); // methodinter target.test(); }
在 ReflectiveAspectJAdvisorFactory#getAdvisor 中把上面@Aspect的类中的方法封装成Advisor对象。
public Advisor getAdvisor(Method candidateAdviceMethod, MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrderInAspect, String aspectName) { validate(aspectInstanceFactory.getAspectMetadata().getAspectClass()); // 得到当前candidateAdviceMethod方法上的所定义的expression表达式,也就是切点 AspectJExpressionPointcut expressionPointcut = getPointcut( candidateAdviceMethod, aspectInstanceFactory.getAspectMetadata().getAspectClass()); if (expressionPointcut == null) { return null; } // 构造一个Advisor,封装了切点表达式和当前方法 return new InstantiationModelAwarePointcutAdvisorImpl(expressionPointcut, candidateAdviceMethod, this, aspectInstanceFactory, declarationOrderInAspect, aspectName); }
不同的Advice对应的不同的类,就是上面说的MethodInterceptor.