spring源码---Aop:解析@Aspect(一)

  aop启动,自然通知类,必不可少,那么spring是如何解析通知类的呢,目前我们从annotation启动过程中,发现spring只是把我们注册到配置类的@Aspect通知类作为一个普通的bean,实例化保存了起来,但是它的内容并没有发挥作用,或者说,当初始化@Aspect通知类的时候,按照我们配置在MyConfig配置类的顺序,前面的普通bean已经实例化,初始化完毕了,他们是如何通过@Aspect通知类进行自动代理的呢?

  本节内容就是找到解析@Aspect的方式。

  我们通过@EnableAspectJAutoProxy注解中发现,里面注册了一个后置处理器,AnnotationAwareAspectJAutoProxyCreator类,所以,猜测@Aspect通知类的解析,与它有关,而它的结构,其实较为庞大,我们在之间的创建代理中初步介绍了,所以这里不细说,它的调用重点是beforeInstaniation中,也就是creatBean()过程中触发。

一,引入

 还记得在我们的aop配置中,加入了一个注解:@EnableAspectJAutoProxy,源码:

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(AspectJAutoProxyRegistrar.class)
public @interface EnableAspectJAutoProxy {
	boolean proxyTargetClass() default false;
	boolean exposeProxy() default false;
}

第一个参数,表示的是代理方式,true使用cglib方式,false使用jdk方式,第二个参数表示暴露方式,解决内部调用不能使用代理的场景。重点我们放在注解里面导入了一个类,很关键:AspectjAutoProxyRegistrar类

class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {
	@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);
			}
		}
	}

}

它作为@Import方式导入,在Configuration...Processor解析配置类的过程中,回解析到该类,而且由于它实现了固定的接口,它并不会被导入BeanFactory中,而是会执行该接口的唯一方法,执行完毕,则把下面AnnotationAwareAspectJAutoProxyCreator注册到BeanFactory中,等待被实例化!

public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(...) {
   return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);
}
private static BeanDefinition registerOrEscalateApcAsRequired(
      Class<?> cls, BeanDefinitionRegistry registry, @Nullable Object source) {
....
   RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);
   beanDefinition.setSource(source);
   beanDefinition.getPropertyValues().add("order", Ordered.HIGHEST_PRECEDENCE);
   beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
   registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition);
   return beanDefinition;
}

二,解析@Aspect

  而refresh()第六步,注册BeanPostProcessor的时候,也进行了getBean()操作,而它为什么没有触发AnnotationAwareAspectJAutoProxyCreator类呢?而是在refresh()第十一步:finishBeanFactoryInitialization()方法中触发?

 答案很明显,第六步名字都叫做注册BeanPostProcessor,很明显处理@Aspect通知类的处理器,还在向容器中注册,这个时候处理bean的postProcessor只是最原始的几个,还没有处理通知类的能力,所以只有等待refresh()第六步注册完毕之后,才能在第十一步 实例化单例bean中触发,现在我们直接来到十一步的getBean()中:

  一般这个时候都是第一次进行实例化,所以getBean()是不存在的,不存在自然就是:getBean-->doGetBean()---->createBean()

  所以来到AbstractAutowireCapableBeanFactory类的createBean()方法中,分为四个步骤,如下:

protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
      throws BeanCreationException {
   RootBeanDefinition mbdToUse = mbd;
   //判断该bean,是否可以被当前加载器修改。
   Class<?> resolvedClass = resolveBeanClass(mbd, beanName); //【1】
   if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
      mbdToUse = new RootBeanDefinition(mbd);
      mbdToUse.setBeanClass(resolvedClass);
   }
   // Prepare method overrides.
      mbdToUse.prepareMethodOverrides();    //【2】
   try {
      // 处理器处理!
      Object bean = resolveBeforeInstantiation(beanName, mbdToUse); //【3】
      if (bean != null) {
         return bean;
      }
   }
   try {
      Object beanInstance = doCreateBean(beanName, mbdToUse, args); //【4】
      return beanInstance;
   }
}

 这里之前创建普通bean的时候,直接研究了第四步,因为走的是第四步,但是这里我们忽略了第三步,aop的实现就在第三步中,调用了后置处理器,这也是后置处理器AbstractAutoProxyCreator有两对before(),after()方法的原因,有一对是在这里调用的,后缀为Instantiation,而有一对的后缀是Initialization,是在初始化的时候调用:

翻译:instantiation 实例化 ----------- initialization 初始化

好,我们进入第三步:resolveBeforeInstaniation() ,bean实例化之前的解析:

如果该方法返回的是null,那么就等着第四步doCreateBean进行实例化-初始化。

protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
   Object bean = null;
   if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
      // Make sure bean class is actually resolved at this point.
      if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
         Class<?> targetType = determineTargetType(beanName, mbd);
         if (targetType != null) {
            bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
            if (bean != null) {
               bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
            }
         }
      }
      mbd.beforeInstantiationResolved = (bean != null);
   }
   return bean;
}

方法1:determineTargetType()方法,确定给bean定义的目标类型,@Target,区分bean的使用范围,如果不在范围,可以不用处理,

参考:https://www.jianshu.com/p/75e0dea370f5

protected Class<?> determineTargetType(String beanName, RootBeanDefinition mbd, Class<?>... typesToMatch) {
   Class<?> targetType = mbd.getTargetType();
   if (targetType == null) {
      targetType = (mbd.getFactoryMethodName() != null ?
            getTypeForFactoryMethod(beanName, mbd, typesToMatch) :
            resolveBeanClass(mbd, beanName, typesToMatch));
      if (ObjectUtils.isEmpty(typesToMatch) || getTempClassLoader() == null) {
         mbd.resolvedTargetType = targetType;
      }
   }
   return targetType;
}

方法2:如果目录类型不为空,则触发了实例化之前的处理:现在开始遍历处理器调用进行处理:

protected Object applyBeanPostProcessorsBeforeInstantiation(Class<?> beanClass, String beanName) {
   for (BeanPostProcessor bp : getBeanPostProcessors()) { //调用后置处理器
      if (bp instanceof InstantiationAwareBeanPostProcessor) { //实例化 aware 明白,意识到,发现
         InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
         Object result = ibp.postProcessBeforeInstantiation(beanClass, beanName);
         if (result != null) {
            return result;
         }
      }
   }
   return null;
}

我们经典的处理器,自然是AbstractAutoProxyCreator类,它的beforeInstantiation()方法:(我们通过@EnableAspectJAutoProxy注解,注册的一个AnnotationAwareAspectJAutoProxyCreator类的父类,复习一下该类的继承结构:

来到AbstractAutoProxyCreator类中: 注意这里还是的参数是待实例化的beanDefinition。而渐渐入场的是spring aop的@Aspect通知类的解析,

  前期在检查该bean,是否已经处理过了,处理过了,就返回null,交给doCreateBean()进行实例化-初始化

  下半段出现了TargetSource 代理源,可参考:https://blog.csdn.net/shenchaohao12321/article/details/85538163

public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
   Object cacheKey = getCacheKey(beanClass, beanName);

   if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) {
      if (this.advisedBeans.containsKey(cacheKey)) { //查缓存,是否处理过了,
         return null;
      } //是否是内部基础类   是否应该跳过
      if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) { //【入】
         this.advisedBeans.put(cacheKey, Boolean.FALSE); //要跳过的直接设置为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()方法,来到它的子类第三层:AspectAwareAdvisorAutoProxyCreator类中:

protected boolean shouldSkip(Class<?> beanClass, String beanName) {
  //发现 候选 Advisor
   List<Advisor> candidateAdvisors = findCandidateAdvisors();
//如果返回的 候选Advisor中的AspectName(通知类的name) 和传入的beanName相同,则返回true
   for (Advisor advisor : candidateAdvisors) {
      if (advisor instanceof AspectJPointcutAdvisor &&
            ((AspectJPointcutAdvisor) advisor).getAspectName().equals(beanName)) {
         return true;
      }
   }
   return super.shouldSkip(beanClass, beanName); //父类方法,直接返回false
}

第一个方法:findCandidateAdvisors(),到达第二层父类:AnnotationAwareAspectAutoProxyCreator类中:

protected List<Advisor> findCandidateAdvisors() {
   // Add all the Spring advisors found according to superclass rules.
   List<Advisor> advisors = super.findCandidateAdvisors();
   // Build Advisors for all AspectJ aspects in the bean factory.
   if (this.aspectJAdvisorsBuilder != null) {
      advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
   }
   return advisors;
}

该方法分为两部分,第一个部分使用父类的find()方法,第二个是使用Builder的build()方法

第一个:AbstractAdvisorAutoProxyCreator 第二层类:

protected List<Advisor> findCandidateAdvisors() {
   return this.advisorRetrievalHelper.findAdvisorBeans();
}

跟入: 结果是什么都没有找到,直接返回一个空集合

public List<Advisor> findAdvisorBeans() {
   // Determine list of advisor bean names, if not cached already.
   String[] advisorNames = this.cachedAdvisorBeanNames;
   if (advisorNames == null) {
      // Do not initialize FactoryBeans here: We need to leave all regular beans
      // uninitialized to let the auto-proxy creator apply to them!
      advisorNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
            this.beanFactory, Advisor.class, true, false);
      this.cachedAdvisorBeanNames = advisorNames;
   }
   if (advisorNames.length == 0) {
      return new ArrayList<>();  //走这里返回了
   }

   List<Advisor> advisors = new ArrayList<>();
   for (String name : advisorNames) {
      if (isEligibleBean(name)) {
         if (this.beanFactory.isCurrentlyInCreation(name)) {
         }
         else {
            try {
               advisors.add(this.beanFactory.getBean(name, Advisor.class));
            }
           ...
   return advisors;
}

第二个:

最后是在BeanFactoryAspectJAdvisorBuilder类中的buildAspectJAdvisors()方法中解析@Aspect:

public List<Advisor> buildAspectJAdvisors() {
   List<String> aspectNames = this.aspectBeanNames; //获取切面名字列表
    //如果 结果过了,自然此处不为null
   if (aspectNames == null) {
      synchronized (this) {  //双重检查
         aspectNames = this.aspectBeanNames;
         if (aspectNames == null) {
            List<Advisor> advisors = new ArrayList<>(); //通知集合
            aspectNames = new ArrayList<>(); //切面名字列表
            String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(  //寻找所有Object类型的bean定义名字
                  this.beanFactory, Object.class, true, false);
            for (String beanName : beanNames) { //遍历所有beanName
               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.
               Class<?> beanType = this.beanFactory.getType(beanName);
               if (beanType == null) {
                  continue;
               }
               if (this.advisorFactory.isAspect(beanType)) { //找到@Aspect 注解的bean
                  aspectNames.add(beanName);
                  AspectMetadata amd = new AspectMetadata(beanType, beanName);
                  if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) {
                     MetadataAwareAspectInstanceFactory factory =
                           new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName);
                     List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory); //【★】获得 类中的方法
                     if (this.beanFactory.isSingleton(beanName)) {
                        this.advisorsCache.put(beanName, classAdvisors);
                     }
                     else {
                        this.aspectFactoryCache.put(beanName, factory);
                     }
                     advisors.addAll(classAdvisors);
                  }
                  else {
                     // Per target or per this.
                     if (this.beanFactory.isSingleton(beanName)) {
                     }
                     MetadataAwareAspectInstanceFactory factory =
                           new PrototypeAspectInstanceFactory(this.beanFactory, beanName);
                     this.aspectFactoryCache.put(beanName, factory);
                     advisors.addAll(this.advisorFactory.getAdvisors(factory));
                  }
               }
            }//保存结果,避免重复解析,返回
            this.aspectBeanNames = aspectNames;
            return advisors;
         }
      }
   }

   if (aspectNames.isEmpty()) {
      return Collections.emptyList();
   }//从缓存中取出Advice by aspectName ,返回,=复制一份
   List<Advisor> advisors = new ArrayList<>();
   for (String aspectName : aspectNames) {
      List<Advisor> cachedAdvisors = this.advisorsCache.get(aspectName);
      if (cachedAdvisors != null) {
         advisors.addAll(cachedAdvisors);
      }
      else {
         MetadataAwareAspectInstanceFactory factory = this.aspectFactoryCache.get(aspectName);
         advisors.addAll(this.advisorFactory.getAdvisors(factory));
      }
   }
   return advisors;
}

重点方法:  位于ReflectiveAspectJAdvisorFactory类中,待下一节进行解析

解析完毕之后的结果:

这三个值,代表了我在通知类中设置的三个方法,而不是代表三个通知类,特别注意这三个方法的注入,不是通过上面find()方法返回得到的,而是通过Builder.build()方法获得的。

  最后返回false

注意,每一次createBean()都会触发shouldSkip()方法,但是如果保存了AspectName,那么自然就回直接返回结果,不会重复进行解析

 

参考链接:https://blog.csdn.net/wangwei19871103/article/details/105208217(大佬膜拜)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值