一、@EnableAspectJAutoProxy注解
在主配置类中添加@EnableAspectJAutoProxy注解,开启aop支持,那么@EnableAspectJAutoProxy到底做了什么?接下来分析下:
@EnableAspectJAutoProxy点进去如下:
此时看到了我们非常熟悉的@Import注解,@Import(AspectJAutoProxyRegistrar.class),进入到AspectJAutoProxyRegistrar发现实现了ImportBeanDefinitionRegistrar如下:
class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar { /** * Register, escalate, and configure the AspectJ auto proxy creator based on the value * of the @{ @link EnableAspectJAutoProxy#proxyTargetClass()} attribute on the importing * { @code @Configuration} class. */ @Override public void registerBeanDefinitions( AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) { 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); } } } }
会调用registerBeanDefinitions方法,跟进到这个方法里面,主要作用就是往Spring容器中注册AnnotationAwareAspectJAutoProxyCreator的Bean的定义信息:
二、AnnotationAwareAspectJAutoProxyCreator继承图
三、AnnotationAwareAspectJAutoProxyCreator创建代理
首先AnnotationAwareAspectJAutoProxyCreator继承了AbstractAutoProxyCreator实现了BeanFactoryAware接口:
所以在创建AnnotationAwareAspectJAutoProxyCreatorBean的过程中初始化方法里面会调用setBeanFactory方法:
在setBeanFactory方法里面调用initBeanFactory来初始化通知者检索帮助类,后面检索通知会用到。
protected void initBeanFactory(ConfigurableListableBeanFactory beanFactory) { this.advisorRetrievalHelper = new BeanFactoryAdvisorRetrievalHelperAdapter(beanFactory); }
其次AnnotationAwareAspectJAutoProxyCreator继承了AbstractAutoProxyCreator实现了InstantiationAwareBeanPostProcessor接口:
该接口定义了2个方法:postProcessBeforeInstantiation和postProcessAfterInstantiation,所以AbstractAutoProxyCreator实现了这2个方法;还记得我们在Spring IoC源码解析篇分析到如下代码:
resolveBeforeInstantiation方法进去就会调到AbstractAutoProxyCreator的postProcessBeforeInstantiation方法
/** * 在创建Bean的流程中还没调用构造器来实例化Bean的时候进行调用(实例化前后) * AOP解析切面以及事务解析事务注解都是在这里完成的 * @param beanClass 当前正在创建的Bean的Class对象 * @param beanName beanName * @return * @throws BeansException */ @Override public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException { //构建我们的缓存key Object cacheKey = getCacheKey(beanClass, beanName); if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) { //如果被解析过直接返回 if (this.advisedBeans.containsKey(cacheKey)) { return null; } /** * 判断是不是基础的Bean(Advice、PointCut、Advisor、AopInfrastructureBean)是就直接跳过 * 判断是不是应该跳过 (AOP解析直接解析出我们的切面信息(并且把我们的切面信息进行缓存),而事务在这里是不会解析的) */ if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) { this.advisedBeans.put(cacheKey, Boolean.FALSE); return null; } } 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; }
接下来进入到shouldSkip(beanClass, beanName)方法(很重要):
protected boolean shouldSkip(Class<?> beanClass, String beanName) { /** * 找到候选的Advisors(通知者或者增强器对象) */ List<Advisor> candidateAdvisors = findCandidateAdvisors(); for (Advisor advisor : candidateAdvisors) { if (advisor instanceof AspectJPointcutAdvisor && ((AspectJPointcutAdvisor) advisor).getAspectName().equals(beanName)) { return true; } } return super.shouldSkip(beanClass, beanName); }
接下来看如何找候选的Advisors,findCandidateAdvisors()方法如下:
@Override protected List<Advisor> findCandidateAdvisors() { //找出事务相关的advisor List<Advisor> advisors = super.findCandidateAdvisors(); //找出Aspect相关的信息之后封装为一个advisor if (this.aspectJAdvisorsBuilder != null) { advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors()); } //返回我们所有的通知 return advisors; }
第一步找事务相关的Advisor:
protected List<Advisor> findCandidateAdvisors() { Assert.state(this.advisorRetrievalHelper != null, "No BeanFactoryAdvisorRetrievalHelper available"); /** * 通过通知者检测帮助类来帮助我们找到通知 * */ return this.advisorRetrievalHelper.findAdvisorBeans(); }
第二步找构建AspectJAdvisors:
/** * 去容器中获取到所有的切面信息保存到缓存中 */ public List<Advisor> buildAspectJAdvisors() { List<String> aspectNames = this.aspectBeanNames; //缓存字段aspectNames没有值 注意实例化第一个单实例bean的时候就会触发解析切面 if (aspectNames == null) { synchronized (this) { aspectNames = this.aspectBeanNames; if (aspectNames == null) { //用于保存所有解析出来的Advisors集合对象 List<Advisor> advisors = new ArrayList<>(); //用于保存切面的名称的集合 aspectNames = new ArrayList<>(); /** * AOP功能中在这里传入的是Object对象,代表去容器中获取到所有的组件的名称,然后再 * 进行遍历,这个过程是十分的消耗性能的,所以说Spring会再这里加入了保存切面信息的缓存。 * 但是事务功能不一样,事务模块的功能是直接去容器中获取Advisor类型的,选择范围小,且不消耗性能。 * 所以Spring在事务模块中没有加入缓存来保存我们的事务相关的advisor */ String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors( this.beanFactory, Object.class, true, false); //遍历我们从IOC容器中获取处的所有Bean的名称 for (String beanName : beanNames) { if (!isEligibleBean(beanName)) { continue; } //通过beanName去容器中获取到对应class对象 Class<?> beanType = this.beanFactory.getType(beanName); if (beanType == null) { continue; } //根据class对象判断是不是切面 @Aspect if (this.advisorFactory.isAspect(beanType)) { //是切面类 //加入到缓存中 aspectNames.add(beanName); //把beanName和class对象构建成为一个AspectMetadata AspectMetadata amd = new AspectMetadata(beanType, beanName); if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) { //构建切面注解的实例工厂 MetadataAwareAspectInstanceFactory factory = new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName); //真正的去获取我们的Advisor List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory); //加入到缓存中 if (this