Spring AOP的总体流程
- 1、注册解析AOP的服务
- 2、解析和加载横切逻辑
- 3、将横切逻辑织入目标Bean中
AnnotationAwareAspectJAutoProxyCreator继承体系图
AnnotationAwareAspectJAutoProxyCreator既实现了SmartInstantiationAwareBeanPostProcessor 又实现了BeanFactoryAware。就可以对容器做一些事情。
AnnotationAwareAspectJAutoProxyCreator 实现了Order接口,所以先于普通的BeanPostProcessor注册,并对普通BeanPostProcessor也能起作用。
AnnotationAwareAspectJAutoProxyCreator 是InstantiationAwareBeanPostProcessor,会在Bean被创建之前,在resolveBeforeInstantiation中被调用。
Spring Aop主要是通过AbstractAutoProxyCreator实现的BeanPostProcessor、InstantiationAwareBeanPostProcessor以及SmartInstantiationAwareBeanPostProcessor接口里面的后置处理器方法,来介入到Spring IOC容器的Bean的实例化以及初始化的过程中对Bean进行AOP的处理的。
所以AbstractAutoProxyCreator类里面的实现的容器级别的后置处理器方法便是介入分析的点:
- 横切逻辑的加载主要是在AbstractAutoProxyCreator类中的postProcessBeforeInstantiation方法中,该方法是在Bean的实例化之前被调用的。
- 横切逻辑织入目标Bean中主要是在AbstractAutoProxyCreator类中的postProcessAfterInitialization方法中,该方法是在Bean的实例化之后被调用的。
AbstractAutoProxyCreator的postProcessAfterInitialization方法是在AbstractAutowireCapableBeanFactory类中的createBean方法中的创建Bean实例方法doCreateBean方法中的的对bean进行初始化方法initializeBean方法中被最终调用的。
initializeBean
public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory implements AutowireCapableBeanFactory { protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) { // 1.激活Aware方法 if (System.getSecurityManager() != null) { AccessController.doPrivileged((PrivilegedAction<Object>) () -> { invokeAwareMethods(beanName, bean); return null; }, getAccessControlContext()); } else { invokeAwareMethods(beanName, bean); } Object wrappedBean = bean; if (mbd == null || !mbd.isSynthetic()) { // 2.在初始化前应用BeanPostProcessor的postProcessBeforeInitialization方法,允许对bean实例进行包装 wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName); } try { // 3.调用初始化方法 invokeInitMethods(beanName, wrappedBean, mbd); } catch (Throwable ex) { throw new BeanCreationException( (mbd != null ? mbd.getResourceDescription() : null), beanName, "Invocation of init method failed", ex); } if (mbd == null || !mbd.isSynthetic()) { // 4.在初始化后应用BeanPostProcessor的postProcessAfterInitialization方法,允许对bean实例进行包装 wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName); } // 5.返回wrappedBean return wrappedBean; } @Override public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName) throws BeansException { Object result = existingBean; // 1.遍历所有注册的BeanPostProcessor实现类,调用postProcessAfterInitialization方法 for (BeanPostProcessor processor : getBeanPostProcessors()) { // 2.在bean初始化后,调用postProcessAfterInitialization方法 Object current = processor.postProcessAfterInitialization(result, beanName); if (current == null) { // 3.如果返回null,则不会调用后续的BeanPostProcessors return result; } result = current; } return result; } }因为AbstractAutoProxyCreator实现了InstantiationAwareBeanPostProcessor接口,所以,AbstractAutowireCapableBeanFactory类中的initializeBean方法中的applyBeanPostProcessorsAfterInitialization方法中的代码processor.postProcessAfterInitialization(result, beanName)方法最终调用的是AbstractAutoProxyCreator类中的postProcessAfterInitialization方法完成的AOP相关横切逻辑的织入的。
由于动态代理对象的创建,并不需要也不会去干预Bean的实例化、属性赋值以及初始化,而初始化结束才意味着Bean被创建完成,因此Spring会等到Bean初始化之后,也就是执行invokeAwareMethods方法之后,才会将相关的横切逻辑给织入到Bean里面。
通过前面的学习了解到,Spring AOP是通过Bean级别的后置处理器在Bean的生命周期中对Bean进行处理的,而针对Bean初始化完之后在进行介入的点就不是很多了,基本就只剩下applyBeanPostProcessorsAfterInitialization方法里面调用的BeanPostProcessor的postProcessAfterInitialization方法了,事实上Spring AOP也正是在此处对bean进行横切逻辑的织入的。
Spring AOP横切逻辑的织入过程:
getEarlyBeanReference
public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport implements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware { //当 Bean 被循环引用, 并且被暴露了, // 则会通过 getEarlyBeanReference 来创建代理类; // 通过判断 earlyProxyReferences 中 // 是否存在 beanName 来决定是否需要对 target 进行动态代理 private final Map<Object, Object> earlyProxyReferences = new ConcurrentHashMap<>(16); @Override public Object getEarlyBeanReference(Object bean, String beanName) { Object cacheKey = getCacheKey(bean.getClass(), beanName); this.earlyProxyReferences.put(cacheKey, bean); return wrapIfNecessary(bean, beanName, cacheKey); } }AbstractAutoProxyCreator类中的getEarlyBeanReference方法,是在AbstractAutowireCapableBeanFactory类中的getEarlyBeanReference方法中的exposedObject = ibp.getEarlyBeanReference(exposedObject, beanName)代码处被调用。
而AbstractAutowireCapableBeanFactory类中的getEarlyBeanReference方法又是在AbstractAutowireCapableBeanFactory类中的doCreateBean方法中的addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean))代码处被调用,addSingletonFactory()方法是提前暴露Bean用于解决SpringIOC容器Bean的循环依赖问题的。
AbstractAutoProxyCreator横切逻辑织入的入口方法:
- postProcessAfterInitialization:正常流程的织入入口。
- getEarlyBeanReference:循环依赖的织入入口。
回到AbstractAutoProxyCreator的postProcessAfterInitialization方法
@Override public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) { if (bean != null) { Object cacheKey = getCacheKey(bean.getClass(), beanName); //当 Bean 被循环引用, 并且被暴露了, // 则会通过 getEarlyBeanReference 来创建代理类; // 通过判断 earlyProxyReferences 中 // 是否存在 beanName 来决定是否需要对 target 进行动态代理 if (this.earlyProxyReferences.remove(cacheKey) != bean) { //该方法将会返回代理类 return wrapIfNecessary(bean, beanName, cacheKey); } } return bean; }如果if (this.earlyProxyReferences.remove(cacheKey) != bean)条件满足
- 1、remove方法执行后返回null
- 2、先前发生循环依赖创建出来的Bean与此时完成初始化的Bean不是同一个
满足上面的两种情况之一,都会以此处的bean为准,对其进行后续的动态代理的织入,毕竟此处的bean已经走完正常的实例化、属性赋值以及初始化的流程了,是最接近成功的bean。
wrapIfNecessary
- 判断当前bean是否需要被代理,如果需要则进行封装
getAdvicesAndAdvisorsForBean
- 返回匹配当前Bean的所有Advice\Advisor\Interceptor
findEligibleAdvisors
- 找到符合条件的Advisor
findCandidateAdvisors
- 找到Spring IoC容器中所有的候选Advisor
关于AnnotationAwareAspectJAutoProxyCreator类中的findCandidateAdvisors方法的解读
public class AnnotationAwareAspectJAutoProxyCreator extends AspectJAwareAdvisorAutoProxyCreator { private BeanFactoryAspectJAdvisorsBuilder aspectJAdvisorsBuilder; @Override protected List<Advisor> findCandidateAdvisors() { // Add all the Spring advisors found according to superclass rules. // 使用注解方式配置AOP的时候还是能够支持对XML配置的AOP的支持的. List<Advisor> advisors = super.findCandidateAdvisors(); // Build Advisors for all AspectJ aspects in the bean factory. if (this.aspectJAdvisorsBuilder != null) { // 为bean工厂中的所有AspectJ方面构建advisor advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors()); } return advisors; } } public class BeanFactoryAspectJAdvisorsBuilder { private final ListableBeanFactory beanFactory; private final AspectJAdvisorFactory advisorFactory; @Nullable private volatile List<String> aspectBeanNames; private final Map<String, List<Advisor>> advisorsCache = new ConcurrentHashMap<>(); private final Map<String, MetadataAwareAspectInstanceFactory> aspectFactoryCache = new ConcurrentHashMap<>(); public List<Advisor> buildAspectJAdvisors() { List<String> aspectNames = this.aspectBeanNames; // 1.如果aspectNames为空,则进行解析 if (aspectNames == null) { synchronized (this) { aspectNames = this.aspectBeanNames; if (aspectNames == null) { List<Advisor> advisors = new ArrayList<>(); //用于保存切面的名称的集合 aspectNames = new ArrayList<>(); //获取所有的beanName // AOP功能中在这里传入的是Object对象,代表去容器中获取到所有的组件的名称,然后再 // 进行遍历,这个过程是十分的消耗性能的,所以说Spring会再这里加入了保存切面信息的缓存。 String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors( this.beanFactory, Object.class, true, false); //遍历我们从IOC容器中获取处的所有Bean的名称 // 1.2 循环遍历所有的beanName,找出对应的增强方法 for (String beanName : beanNames) { // 1.3 不合法的beanName则跳过,默认返回true,子类可以覆盖实现,AnnotationAwareAspectJAutoProxyCreator // 实现了自己的逻辑,支持使用includePatterns进行筛选 if (!isEligibleBean(beanName)) { continue; } // We must be careful not to instantiate beans eagerly as in this case they // would be cached by the Spring container but would not have been weaved. //获取对应的bean的类型 Class<?> beanType = this.beanFactory.getType(beanName); if (beanType == null) { continue; } //提取@Aspect注解标记的Class if (this.advisorFactory.isAspect(beanType)) { //是切面类 //加入到缓存中 // 将存在Aspect注解的beanName添加到aspectNames列表 aspectNames.add(beanName); // 新建切面元数据 AspectMetadata amd = new AspectMetadata(beanType, beanName); // 获取per-clause的类型是SINGLETON if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) { // 使用BeanFactory和beanName创建一个BeanFactoryAspectInstanceFactory,主要用来创建切面对象实例 MetadataAwareAspectInstanceFactory factory = new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName); //Aspect里面的advice和pointcut被拆分成一个个的advisor, // advisor里的advice和pointcut是1对1的关系 // 1.5 解析标记AspectJ注解中的增强方法 List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory); if (this.beanFactory.isSingleton(beanName)) { //单例则直接将Advisor类存到缓存 this.advisorsCache.put(beanName, classAdvisors); } else { // 否则将其对应的工厂缓存 // 如果不是单例,则将factory放到缓存,之后可以通过factory来解析增强方法 this.aspectFactoryCache.put(beanName, factory); } // 1.7 将解析的增强器添加到advisors advisors.addAll(classAdvisors); } else { // 如果per-clause的类型不是SINGLETON // Per target or per this. if (this.beanFactory.isSingleton(beanName)) { // 名称为beanName的Bean是单例,但切面实例化模型不是单例,则抛异常 throw new IllegalArgumentException("Bean with name '" + beanName + "' is a singleton, but aspect instantiation model is not singleton"); } MetadataAwareAspectInstanceFactory factory = new PrototypeAspectInstanceFactory(this.beanFactory, beanName); // 将factory放到缓存,之后可以通过factory来解析增强方法 this.aspectFactoryCache.put(beanName, factory); // 解析标记AspectJ注解中的增强方法,并添加到advisors中 advisors.addAll(this.advisorFactory.getAdvisors(factory)); } } } // 1.9 将解析出来的切面beanName放到缓存aspectBeanNames this.aspectBeanNames = aspectNames; // 1.10 最后返回解析出来的增强器 return advisors; } } } // 2.如果aspectNames不为null,则代表已经解析过了,则无需再次解析 // 2.1 如果aspectNames是空列表,则返回一个空列表。空列表也是解析过的,只要不是null都是解析过的。 if (aspectNames.isEmpty()) { return Collections.emptyList(); } // 2.2 aspectNames不是空列表,则遍历处理 List<Advisor> advisors = new ArrayList<>(); for (String aspectName : aspectNames) { // 根据aspectName从缓存中获取增强器 List<Advisor> cachedAdvisors = this.advisorsCache.get(aspectName); if (cachedAdvisors != null) { // 根据上面的解析,可以知道advisorsCache存的是已经解析好的增强器,直接添加到结果即可 advisors.addAll(cachedAdvisors); } else { // 如果不存在于advisorsCache缓存,则代表存在于aspectFactoryCache中, // 从aspectFactoryCache中拿到缓存的factory,然后解析出增强器,添加到结果中 MetadataAwareAspectInstanceFactory factory = this.aspectFactoryCache.get(aspectName); advisors.addAll(this.advisorFactory.getAdvisors(factory)); } } // 返回增强器 return advisors; } }更详细的横切逻辑的加载与解析:Spring5AOP——AbstractAutoProxyCreator横切逻辑的加载与解析
回到AbstractAdvisorAutoProxyCreator类的findEligibleAdvisors方法中
findAdvisorsThatCanApply
- 从所有候选的Advisor中找出符合条件的
AopUtils.findAdvisorsThatCanApply
- 委托AopUtils.findAdvisorsThatCanApply方法筛选出匹配Bean的Advisors
AopUtils.canApply
- 判断当前Advisor的Pointcut是否匹配当前bean
AopUtils.canApply(Pointcut pc, Class<?> targetClass, boolean hasIntroductions)
- canApply(pca.getPointcut(), targetClass, hasIntroductions)
matches
- !pc.getClassFilter().matches(targetClass)
- 对Bean进行初筛
到此getAdvicesAndAdvisorsForBean方法的调用链就分析的差不多了,回到AbstractAutoProxyCreator类中的wrapIfNecessary方法中。
public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport implements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware { /** * Spring实现Bean代理的核心方法。wrapIfNecessary在两处会被调用,一处是getEarlyBeanReference, * 另一处是postProcessAfterInitialization */ protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) { //已经被处理过 // 1.判断当前bean是否在targetSourcedBeans缓存中存在(已经处理过),如果存在,则直接返回当前bean if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) { return bean; } //不需要被织入逻辑的 // 2.在advisedBeans缓存中存在,并且value为false,则代表无需处理 if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) { return bean; } //是不是基础的bean 是不是需要跳过的 // 3.bean的类是aop基础设施类 || bean应该跳过,则标记为无需处理,并返回 if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) { this.advisedBeans.put(cacheKey, Boolean.FALSE); return bean; } // Create proxy if we have advice. // 返回匹配当前Bean的所有Advice\Advisor\Interceptor Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null); // 5.如果存在增强器则创建代理 if (specificInterceptors != DO_NOT_PROXY) { this.advisedBeans.put(cacheKey, Boolean.TRUE); //创建Bean对应的代理,SingletonTargetSource用于封装实现类的信息 // 5.1 创建代理对象:这边SingletonTargetSource的target属性存放的就是我们原来的bean实例(也就是被代理对象), // 用于最后增加逻辑执行完毕后,通过反射执行我们真正的方法时使用(method.invoke(bean, args)) Object proxy = createProxy( bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean)); // 5.2 创建完代理后,将cacheKey -> 代理类的class放到缓存 this.proxyTypes.put(cacheKey, proxy.getClass()); // 返回代理对象 return proxy; } //该Bean是不需要进行代理的,下次就不需要重复生成了 this.advisedBeans.put(cacheKey, Boolean.FALSE); return bean; } }-
当执行完getAdvicesAndAdvisorsForBean方法之后,就可以从候选的Advisor列表里筛选出匹配于当前Bean的Advisor列表,获取到Advisor列表之后就会接着执行后续的创建动态代理的步骤了。
-
由于getAdvicesAndAdvisorsForBean筛选出匹配的Advisor了,将该Bean对应的cacheKey写入到advisedBeans中,并将对应的值设置为true,表示对该Bean进行过Spring AOP的处理了。
-
之后就会调用createProxy方法去创建目标代理对象实例,创建好动态代理实例之后,就会动态代理实例类型给保存到proxyTypes的缓存里面,并将动态代理实例返回,这样就完成了wrapIfNecessary方法的执行。
-
如果没有getAdvicesAndAdvisorsForBean没有筛选出匹配的Advisor的话,就证明该Bean不需要织入横切逻辑,此时就会在advisedBeans里给该Bean设置对应的cacheKey和false,以表明该bean是不需要被织入的。
参考: https://segmentfault.com/a/1190000015830477
https://zhuanlan.zhihu.com/p/104521455