Spring AOP源码(三):创建AOP相关的Bean

  在Spring AOP源码(二):BeanDefinition的准备工作中,介绍了Spring准备AOP相关的BeanDefinition对象,同样的对于普通的bean对象的创建此处不再赘述,主要分析动态代理创建器、Advisor是如何实例化的。

1、动态代理模式创建器实例化

  在上一篇中已经知道Spring中AOP的自动代理模式创建器AnnotationAwareAspectJAutoProxyCreator。

 

     AnnotationAwareAspectJAutoProxyCreator实现了BeanPostProcessor接口,同时也实现了Ordered接口。

  在IOC容器创建的过程中,registerBeanPostProcessors(beanFactory)是对容器中BeanPostProcessor做处理的方法,核心流程:

  PostProcessorRegistrationDelegate#registerBeanPostProcessors核心伪代码如下:

 1 // 注册并实例化AOP的动态代理
 2 public static void registerBeanPostProcessors(
 3       ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {
 4 
 5    // 找到所有实现了BeanPostProcessor接口的类
 6    String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);
 7    // ......
 8    // 定义存放实现了Ordered接口的BeanPostProcessor的name集合
 9    List<String> orderedPostProcessorNames = new ArrayList<>();
10     // ......
11     // 注册所有实现Ordered的beanPostProcessor
12    List<BeanPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size());
13    for (String ppName : orderedPostProcessorNames) {
14       // 根据ppName找到对应的BeanPostProcessor实例对象
15       BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
16       // 将实现了Ordered接口的BeanPostProcessor添加到orderedPostProcessors集合中
17       orderedPostProcessors.add(pp);
18    }
19    //  注册实现了Ordered接口的BeanPostProcessor实例添加到beanFactory中
20    registerBeanPostProcessors(beanFactory, orderedPostProcessors);
21    // ......
22 }

  有一点需要注意,AnnotationAwareAspectJAutoProxyCreator实现了InstantiationAwareBeanPostProcessor接口,这个在将BeanPostProcessor注册到beanPostProcessors容器中时,会将AbstractBeanFactory属性hasInstantiationAwareBeanPostProcessors实例化后置处理器注册标识设置为true。

  AbstractBeanFactory#addBeanPostProcessor核心伪代码如下:

 1 // 将BeanPostProcessor注册到beanPostProcessors容器中
 2 public void addBeanPostProcessor(BeanPostProcessor beanPostProcessor) {    
 3     
 4    // 如果beanPostProcessors集合中已经存在此beanPostProcessors对象,移除该对象
 5    this.beanPostProcessors.remove(beanPostProcessor);
 6 
 7    // beanPostProcessor是为InstantiationAwareBeanPostProcessor类型,Bean对象实例化后置处理器注册标识设置为true
 8    if (beanPostProcessor instanceof InstantiationAwareBeanPostProcessor) {
 9       this.hasInstantiationAwareBeanPostProcessors = true;
10    }
11    
12    // 将beanPostProcessor加入后置处理器集合中
13    this.beanPostProcessors.add(beanPostProcessor);
14 }

  hasInstantiationAwareBeanPostProcessors标识在后续的Advisor实例化中会用到,这里先记住这个结论。

2、Advisor的实例化

2.1、AOP常用五大通知Advice的类图

1、前置通知 AspectJMethodBeforeAdvice

2、后置通知 AspectJAfterAdvice

3、环绕通知 AspectJAroundAdvice

4、后置返回通知 AspectJAfterReturningAdvice

5、后置异常通知 AspectAfterThrowingAdvice

6、结论

  通过AOP常用的五大Advice的类图发现,AOP的Advice没有实现BeanFactoryPostProcessor、BeanPostProcessor接口,所以Advisor与普通的bean实例化、初始化一样,在IOC容器启动过程中,finishBeanFactoryInitialization(beanFactory)方法是完成容器中普通bean实例化的方法。

2.2、Advisor的实例化

1、Advisor实例化的时机

有个问题需要我们思考,Advisior是在哪个步骤做实例化的呢,我们先看下Bean的生命周期:

  1、bean实例化前的处理
  2、bean的实例化 class.newInstance()
  3、bean初始化前的处理
  4、bean初始化
  5、bean初始化后的处理
  6、bean的销毁
  Spring是在哪个周期来实现Advisor实例化的呢?

2、Advisor创建的核心流程

  由此上面的流程可知,在aop切面aspect的普通bean标签的实例化时,在实例化之前,查找beanFactory容器中所有实现Advisor的beanDefinition并做实例化操作,并将遍历Advisor集合,如果Advisor集合中的存在某个Advisor切面的AspectName与正在创建的beanName相同,则跳过resolveBeforeInstantiation处理。

  AspectJAwareAdvisorAutoProxyCreator#shouldSkip 查找并实例化Advisor入口核心代码:
 1 // 是否应该跳过
 2 protected boolean shouldSkip(Class<?> beanClass, String beanName) {
 3    // 查找并创建容器中所以的Advisor
 4    List<Advisor> candidateAdvisors = findCandidateAdvisors();
 5    // 遍历Advisor集合
 6    for (Advisor advisor : candidateAdvisors) {
 7       // Advisor是AspectJPointcutAdvisor类型并且Advisor中的切面与正在创建的beanName相同
 8       if (advisor instanceof AspectJPointcutAdvisor &&
 9             ((AspectJPointcutAdvisor) advisor).getAspectName().equals(beanName)) {
10          return true;
11       }
12    }
13    return super.shouldSkip(beanClass, beanName);
14 }

  AbstractAdvisorAutoProxyCreator#findAdvisorBeans 查找并实例化Advisor的核心伪代码:

 1 // 查找容器中所有的Advisor对象
 2 public List<Advisor> findAdvisorBeans() {
 3    // 获取已经缓存的Advisor的beanName集合
 4    String[] advisorNames = this.cachedAdvisorBeanNames;
 5    
 6    if (advisorNames == null) {
 7       // 获取当前BeanFactory中所有实现了Advisor接口的bean的名称
 8       advisorNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
 9             this.beanFactory, Advisor.class, true, false);
10       this.cachedAdvisorBeanNames = advisorNames;
11    }
12    
13    if (advisorNames.length == 0) {
14       return new ArrayList<>();
15    }
16    
17    // 对获取到的实现Advisor接口的bean的名称进行遍历
18    List<Advisor> advisors = new ArrayList<>();
19    // 循环所有的beanName,找出对应的增强方法
20    for (String name : advisorNames) {
21         // 创建Advisor, 并将当前bean添加到Advisor集合中,用于后续遍历
22         advisors.add(this.beanFactory.getBean(name, Advisor.class));
23    }
24    return advisors;
25 }

  getBean -> doGetBean -> CreateBean -> doCreateBean,此处便是创建Advisor的bean的地方。

  到这里,就可以回答Advisor实例化的时机了,在创建配置文件中的首个bean标签时,在实例化之前会对判断是否提前生成代理对象,在shouldSkip中查询容器中所有实现Advisor的beanName,并通过getBean创建AOP的Advisor对象。

3、Advisor实例化步骤

3.1、Advisor的有参构造函数

  Spring中,一般bean都是调用无参构造函数,通过反射class.newInstance()来完成实例化的。但是Advisor没有无参构造函数,只有参构造函数,构造函数详情。
1 // 为给定的Advice创建一个AspectJPointcutAdvisor实例
2 public AspectJPointcutAdvisor(AbstractAspectJAdvice advice) {
3    Assert.notNull(advice, "Advice must not be null");
4    this.advice = advice;
5    this.pointcut = advice.buildSafePointcut();
6 }

3.2、Advice的有参构造函数

  通过AOP常用五大通知Advice的类图可知,AbstractAspectJAdvice是AOP五大通知的父类,我们看下具体的Advice的构造函数
  AspectJAfterAdvice - 后置通知的有参构造函数
1 public AspectJAfterAdvice(
2       Method aspectJBeforeAdviceMethod, AspectJExpressionPointcut pointcut, AspectInstanceFactory aif) {
3 
4    super(aspectJBeforeAdviceMethod, pointcut, aif);
5 }
  AspectJMethodBeforeAdvice - 前置通知的有参构造函数
1 public AspectJMethodBeforeAdvice(
2       Method aspectJBeforeAdviceMethod, AspectJExpressionPointcut pointcut, AspectInstanceFactory aif) {
3 
4    super(aspectJBeforeAdviceMethod, pointcut, aif);
5 }

  AspectJAroundAdvice - 环绕通知的有参构造函数

1 public AspectJAroundAdvice(
2       Method aspectJAroundAdviceMethod, AspectJExpressionPointcut pointcut, AspectInstanceFactory aif) {
3 
4    super(aspectJAroundAdviceMethod, pointcut, aif);
5 }

  AspectJAfterReturningAdvice - 后置返回通知的有参构造函数

1 public AspectJAfterReturningAdvice(
2       Method aspectJBeforeAdviceMethod, AspectJExpressionPointcut pointcut, AspectInstanceFactory aif) {
3 
4    super(aspectJBeforeAdviceMethod, pointcut, aif);
5 }

  AspectJAfterThrowingAdvice - 后置异常通知有参构造函数

1 public AspectJAfterThrowingAdvice(
2       Method aspectJBeforeAdviceMethod, AspectJExpressionPointcut pointcut, AspectInstanceFactory aif) {
3 
4    super(aspectJBeforeAdviceMethod, pointcut, aif);
5 }

  advisor的有参构造函数中,参数为Advice; Advice的有参构造函数中,参数为Method、AspectJExpressionPointcut、AspectInstanceFactory。要想实例化Advisor,必须先实例化Advice; 若要实例化Advice,必须先实例化Method、AspectJExpressionPointcut、AspectInstanceFactory,这个实例化过程是很麻烦的。

3.3、Advice有参构造函数中的参数实例

  Advisor实例化的核心流程:

 

 

posted @ 2022-12-28 20:35  无虑的小猪  阅读(166)  评论(0编辑  收藏  举报