六. 容器的创建流程(关联Aspect部分)

笨鸟先飞
• 阅读 1149
本篇文章只是简单的关联 Aspect 部分内容。

做一个独立出来的 容器创建步骤中 的 Aspect 部分。为了不让AOP 过于冗余。做一个简单的抽离。
整理的比较乱:有时间的时候 在整理下用词吧。 TODO

话不多说,直接进入正文吧。

下面说下 容器创建流程中的 Aspect 部分。

1. 流程

1.1 通过配置类,创建 IOC 容器

 // 创建 IOC 容器
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(MainConfigOfAOP.class);

1.2 注册配置类,调用 refresh() 刷新容器

public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) {
        this();
        register(annotatedClasses);
        refresh();
}

1.3 注册 bean 的后置处理器: BeanPostProcessors

实现步骤:

// Register bean processors that intercept bean creation.
registerBeanPostProcessors(beanFactory);

其实只是定义还没有创建。 定义信息(BeanDefinitions)

// 通过注解获取所有的后置处理器
String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);

// 创建注册 beanPostProcessor
BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);

registerBeanPostProcessors(beanFactory, orderedPostProcessors);


// Finally, re-register all internal BeanPostProcessors.
sortPostProcessors(internalPostProcessors, beanFactory);
registerBeanPostProcessors(beanFactory, internalPostProcessors);

-->
  
beanFactory.addBeanPostProcessor(postProcessor);

1.3.1 获取所有后置处理器

六.  容器的创建流程(关联Aspect部分)

1.3.2 按照排序规则,依次创建 注册 BeanPostProcessor

给容器中添加 创建BeanPostProcessor对象

  • 1)、优先注册实现了PriorityOrdered接口的BeanPostProcessor;
  • 2)、再给容器中注册实现了Ordered接口的BeanPostProcessor;
  • 3)、注册没实现优先级接口的BeanPostProcessor;
// First, register the BeanPostProcessors that implement PriorityOrdered.
sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);

// Next, register the BeanPostProcessors that implement Ordered.
List<BeanPostProcessor> orderedPostProcessors = new ArrayList<>();
for (String ppName : orderedPostProcessorNames) {
  BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
  orderedPostProcessors.add(pp);
  if (pp instanceof MergedBeanDefinitionPostProcessor) {
    internalPostProcessors.add(pp);
  }
}
sortPostProcessors(orderedPostProcessors, beanFactory);
registerBeanPostProcessors(beanFactory, orderedPostProcessors);

// Now, register all regular BeanPostProcessors.
List<BeanPostProcessor> nonOrderedPostProcessors = new ArrayList<>();
for (String ppName : nonOrderedPostProcessorNames) {
  BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
  nonOrderedPostProcessors.add(pp);
  if (pp instanceof MergedBeanDefinitionPostProcessor) {
    internalPostProcessors.add(pp);
  }
}
registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors);

// Finally, re-register all internal BeanPostProcessors.
sortPostProcessors(internalPostProcessors, beanFactory);
registerBeanPostProcessors(beanFactory, internalPostProcessors);

这里面 创建 BeanPostProcessor 的方法 getBean 单独拎出来 放到下面统一说。

1.3.3 添加到 beanFactory

beanFactory.addBeanPostProcessor(postProcessor);

注册到 beanFactory 中

以上是创建和注册AnnotationAwareAspectJAutoProxyCreator的过程

AnnotationAwareAspectJAutoProxyCreator => InstantiationAwareBeanPostProcessor

1.4 注册其他的bean

比如 业务逻辑 (MathCalculator 对应的组件) 和 切面组件(LogAspect 对应的组件)

步骤 : finishBeanFactoryInitialization(beanFactory);

// Instantiate all remaining (non-lazy-init) singletons.
beanFactory.preInstantiateSingletons();

getBean(beanName);

遍历容器中的所有 bean,依次创建对象 getBean(beanName);

六.  容器的创建流程(关联Aspect部分)
在创建bean 的时候,这里会有所不同

1) AnnotationAwareAspectJAutoProxyCreator在所有bean创建之前会有一个拦截,InstantiationAwareBeanPostProcessor,会调用postProcessBeforeInstantiation()

2) 先从缓存中获取当前bean,如果能获取到,说明bean是之前被创建过的,直接使用,

否则再创建;只要创建好的Bean都会被缓存起来

因为最后获取所有 bean 的 创建。 而有些已经在前面的步骤先行创建好了。 只需要从缓存中获取就好。

// Eagerly check singleton cache for manually registered singletons.
Object sharedInstance = getSingleton(beanName);

为空再去创建 bean
return createBean(beanName, mbd, args);
a. AnnotationAwareAspectJAutoProxyCreator 在 createBean() 之前拦截

所谓的拦截,就是一段代码提前执行。

所在类 : org/springframework/beans/factory/support/AbstractAutowireCapableBeanFactory.java

try {
   // Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
   Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
   if (bean != null) {
      return bean;
   }
}

AnnotationAwareAspectJAutoProxyCreator 会在任何bean创建之前先尝试返回bean的实例【BeanPostProcessor是在Bean对象创建完成初始化前后调用的】

执行的方法

@Nullable
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;
}

其中 bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);

和 bean = applyBeanPostProcessorsAfterInitialization(bean, beanName); 为重要的功能。

只针对 : InstantiationAwareBeanPostProcessor 的后置处理器

@Nullable
protected Object applyBeanPostProcessorsBeforeInstantiation(Class<?> beanClass, String beanName) {
        for (BeanPostProcessor bp : getBeanPostProcessors()) {
            if (bp instanceof InstantiationAwareBeanPostProcessor) {
                InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
                Object result = ibp.postProcessBeforeInstantiation(beanClass, beanName);
                if (result != null) {
                    return result;
                }
            }
        }
        return null;
    }

解析BeforeInstantiation

希望后置处理器在此能返回一个代理对象;如果能返回代理对象就使用,如果不能就继续

这部分放到 切面的部分来说 。 等待补充 TODO

2. 获取创建bean的过程: BeanPostProcessor

Object beanInstance = doCreateBean(beanName, mbdToUse, args);

doCreateBean 的实现步骤

也就是创建 BeanPostProcessor 的过程。同样的也是创建 bean 的过程

这个时候 bean 只是有一个name 什么都没有。

对应的创建类: org/springframework/beans/factory/support/AbstractBeanFactory.java

六.  容器的创建流程(关联Aspect部分)

具体流程步骤的类 : org/springframework/beans/factory/support/AbstractAutowireCapableBeanFactory.java

2.1 创建 bean 的实例

源码如下:

if (instanceWrapper == null) {
  instanceWrapper = createBeanInstance(beanName, mbd, args);
}

里面的方法不再过多介绍 最后通过类的无参够着函数 实例化类
// No special handling: simply use no-arg constructor.
return instantiateBean(beanName, mbd);

2.2 设置 bean 的属性

源码如下:

populateBean(beanName, mbd, instanceWrapper);

里面的细节不再过多解释,通过反射。为里面类的属性赋值

2.3 初始化 bean

源码如下:

exposedObject = initializeBean(beanName, exposedObject, mbd);

初始化 bean 的时候可以做很多工作。

六.  容器的创建流程(关联Aspect部分)

作为 和 https://segmentfault.com/a/1190000021554606 的对比。

本文主要增加了 Aware 部分。

invokeAwareMethods(beanName, bean);

所以初始化 bean 的步骤如下

  • 1)invokeAwareMethods():处理Aware接口的方法回调
  • 2)applyBeanPostProcessorsBeforeInitialization():

    应用后置处理器的postProcessBeforeInitialization()

  • 3)invokeInitMethods();执行自定义的初始化方法
  • 4)applyBeanPostProcessorsAfterInitialization();执行后置处理器的postProcessAfterInitialization();

2.4 创建成功

initBeanFactory()

debug 的时候 以 AnnotationAwareAspectJAutpProxyCreator 为例。

AnnotationAwareAspectJAutpProxyCreator 也就是 使用 @EnableAspectJAutoProxy 注解定义的 bean

点赞
收藏
评论区
推荐文章
Stella981 Stella981
3年前
Spring 学习笔记(四):Spring AOP
@\TOC\1概述本文主要讲述了AOP的基本概念以及在Spring中AOP的几种实现方式。2AOPAOP,即AspectOrientedProgramming,面向切面编程,与OOP相辅相成。类似的,在OOP中,以类为程序的基本单元,在AOP中的基本单元是Aspect
Stella981 Stella981
3年前
PHP代码静态分析工具PHPStan
<blockquote最近发现自己写的PHP代码运行结果总跟自己预想的不一样,排查时发现大多是语法错误,在运行之前错误已经种下。可能是自己粗心大意,或者说<codephpl</code检测太简单,不过的确是有一些语法错误埋藏得太深(毕竟PHP是动态语言),那么有没有办法,在代码代码正式运行之前,把语法错误全找出来呢?</blockquote<p
Stella981 Stella981
3年前
Spring AOP @Aspect 基本用法
Spring使用的AOP注解分为三个层次:前提条件是在xml中放开了<aop:aspectjautoproxyproxytargetclass"true"/<!开启切面编程功能1、@Aspect放在类头上,把这个类作为一个切面。2、@Pointcut放在方法头上,定义一个可被别的方法引用的切入点
Stella981 Stella981
3年前
SpringAOP
Aspect切面:一个关注点的模块化,这个关注点可能会横切多个对象Joinpoint连接点:程序执行过程中的某个特定的点Advice通知:在切面的某个连接点上执行的动作Pointcut切入点:匹配连接点的断言,在AOP的通知和一个切入点表达式关联Introduction引入:在不修改类代码的前提下,为类添加新的方法
Stella981 Stella981
3年前
Spring Aspect Oriented Programming
  本文是一篇SpringAOP的基础知识分析文章,其中不牵扯源码分析,只包含AOP中重要概念的讲解,分析,以及SpringAOP的用法。    Spring从2.0版本引入了更加简单却强大的基于xml和AspectJ注解的面向切面的编程方式。在深入了解如何用Spring进行面向切面的编程前,我们先了解AOP中的几个重要的基本概念,这几个概念
Easter79 Easter79
3年前
Spring系列(五) 容器初始化过程源码
IoC/DI的概念容器是Spring的核心之一(另一个核心是AOP).有了容器,IOC才可能实现.什么使IoC?IoC就是将类自身管理的与其由依赖关系的对象的创建/关联和管理交予容器实现,容器按照配置(比如xml文件)来组织应用对象的创建和关联.什么使DI?DI是IoC的实现方式,由容器
Stella981 Stella981
3年前
Spring Boot 动态数据源(Spring 注解数据源)
<divclass"contentdetailmarkdownbody"<p本文实现案例场景:<br某系统除了需要从自己的主要数据库上读取和管理数据外,还有一部分业务涉及到其他多个数据库,要求可以在任何方法上可以灵活指定具体要操作的数据库。</p<p为了在开发中以最简单的方法使用,本文基于注解和AOP的方法实现,在springbo
Wesley13 Wesley13
3年前
ThinkPHP 根据关联数据查询 hasWhere 的使用实例
很多时候,模型关联后需要根据关联的模型做查询。场景:广告表(ad),广告类型表(ad\_type),现在需要筛选出广告类型表中id字段为1且广告表中status为1的列表先看关联的设置部分 publicfunctionadType(){return$thisbelongsTo('A
Wesley13 Wesley13
3年前
AOP概念详解笔记
切面(Aspect)一个关注点的模块化,这个关注点实现可能另外横切多个对象。事务管理是一个很好的横切关注点例子。切面用Spring的Advisor或拦截器实现, 然后可以通过@Aspect标注或在applictionContext.xml中进行配置: <aop:aspect id"fourAdviceAspect" r
Stella981 Stella981
3年前
Spring3核心技术之AOP配置
在Spring配置文件中,所有AOP相关定义必须放在<aop:config标签下,该标签下可以有<aop:pointcut、<aop:advisor、<aop:aspect标签,配置顺序不可变。!(http://static.oschina.net/uploads/img/201511/25003650_G0NP.jpg)●
Easter79 Easter79
3年前
Spring技术内幕总结
AOP是AspectOrientedProgramming(面向方面/切面编程)的简称。Aspect是一种新的模块化机制,用来描述分散在对象、类或函数中的横切关注点。分离关注点使解决特定领域问题的代码从业务逻辑中独立出来,业务逻辑的代码中不再含有针对特定领域问题代码的调用,业务逻辑同特定领域问题的关系通过切面来封装、维护,这样原来分散在整个应用程序中的变
笨鸟先飞
笨鸟先飞
Lv1
近乡情更怯,不敢问来人。
文章
4
粉丝
0
获赞
0