【Spring】Spring5 源码中常用接口的底层原理

本文将介绍Spring源码中较为常用的几个接口的底层实现原理:

  • ImportBeanDefinitionRegistrar
  • BeanPostProcessor
  • BeanFactoryPostProcessor
  • BeanDefinitionRegistryPostProcessor
  • Aware

ImportBeanDefinitionRegistrar

ImportBeanDefinitionRegistrar接口的实现类用在@Import注解中,用于向IoC容器中自定义注册组件

1
2
3
@Import({MyImportBeanDefinitionRegistrar.class})
public class SpringConfig {
}

@Import 注解中可以传入ImportBeanDefinitionRegistrar接口的实现类。

image-20210628212948066

xxx通过调用ImportBeanDefinitionRegistrar接口实现类的registerBeanDefinitions() 方法,可以自定义地给容器中添加组件。方法参数:

  • importingClassMetadata:当前标注Import注解的类(即SpringConfig类)的所有注解信息
  • registry:所有bean对象都通过此对象注册,可以使用该对象给容器中注册一个bean

image-20210628213321835

使用方法:把所有要添加到容器中的bean调用registry.registerBeanDefinition(String beanName, BeanDefinition beanDefinition)方法手动注册到容器中。该方法需要传入beanName和一个实现了beanDefinition接口的类的对象(通常使用其实现类RootBeanDefinition

image-20210628215427638

使用实例:

image-20210628220119176

BeanPostProcessor

BeanPostProcessor:bean后置处理器。其用于在bean的初始化前后进行一些处理工作(此时已经调用了构造函数并使用了set方法为bean赋值):

  • postProcessBeforeInitialization():在初始化方法之前工作
  • postProcessAfterInitialization():在初始化方法之后工作

自定义后置处理器实现BeanPostProcessor的方法,并将其注册到容器中。之后所有的bean对象在初始化方法前后都会进入该类的方法中执行相应处理。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
@Component
public class MyBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
// bean:当前被处理的bean对象
System.out.println("====> postProcessBeforeInitialization ... " + beanName + ": " + bean);

// 可以对bean进行一些包装
return bean;
}

@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("====> postProcessAfterInitialization ... " + beanName + ": " + bean);

// 可以对bean进行一些包装
return bean;
}
}

BeanPostProcessor执行流程源码分析

  1. 容器调用bean的构造方法创建对象
  2. populateBean():容器调用bean的set方法为bean对象的属性赋值(红色框)
  3. initializeBean():容器为bean做初始化操作(黄色框)

方法栈位置:AbstractAutowireCapableBeanFactory.java

image-20210629163559536

======> 进入黄色框的initializeBean()方法:

  • 执行invokeAwareMethods()方法(绿色框)
  • 执行applyBeanPostProcessorsBeforeInitialization()方法(红色框)
  • 执行invokeInitMethods()方法完成初始化(黄色框)
  • 执行applyBeanPostProcessorsAfterInitialization()方法(红色框)

image-20210630214340913

======> 进入红色框的applyBeanPostProcessorsBeforeInitialization()方法:

遍历得到容器中所有的BeanPostProcessor,并一执行BeanPostProcessorpostProcessBeforeInitialization()方法,将bean对象逐一经过每个BeanPostProcessor处理器。一旦返回null,跳出for循环后续不再执行。

image-20210629164433894

BeanFactoryPostProcessor

BeanFactoryPostProcessor:bean工厂后置处理器。调用时机:在BeanFactory标准初始化之后调用,此时所有组件的定义已经加载,但是组件的实例还没有被初始化创建。其作用:用来定制和修改BeanFactory的内容

1
2
3
4
5
6
7
8
@Component
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
// 可以对beanFactory进行一些修改
System.out.println("====> postProcessBeanFactory ... bean的数量:" + beanFactory.getBeanDefinitionCount());
}
}

BeanFactoryPostProcessor执行流程源码分析

  1. refresh()方法中调用invokeBeanFactoryPostProcessors()

image-20210705205828372

  1. 在其内的方法栈中先按照类型获取到postProcessorNames

image-20210709100017919

  1. 将获取到的:postProcessorNames按照优先级排序

image-20210709100256718

  1. 按照优先级次序依次执行

image-20210709095828532

image-20210709100124077

上述过程在初始化创建其他组件之前执行,在BeanDefinitionRegistryPostProcessor之后执行。

BeanDefinitionRegistryPostProcessor

BeanDefinitionRegistryPostProcessor继承自BeanFactoryPostProcessor。其在所有bean定义信息将要被加载,且bean实例还未创建时执行,因此其在BeanFactoryPostProcessor的方法之前执行。作用:利用传入的BeanDefinitionRegistry给容器中再添加一些组件

每个BeanDefinitionRegistryPostProcessor接口的实现类都需要实现postProcessBeanDefinitionRegistry()方法和postProcessBeanFactory()方法,执行顺序:先前者再后者。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
@Component
public class MyBeanDefinitionRegistryProcessor implements BeanDefinitionRegistryPostProcessor {
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
// 首先执行
// registry: bean定义信息的保存中心
// BeanFactory就是按照BeanDefinitionRegistry中保存的每一个bean定义信息创建bean实例
System.out.println("====> postProcessBeanDefinitionRegistry ... bean的数量:" + registry.getBeanDefinitionCount());

RootBeanDefinition rootBeanDefinition = new RootBeanDefinition(Color.class);
// 二者效果相同↑
//AbstractBeanDefinition rootBeanDefinition = BeanDefinitionBuilder.rootBeanDefinition(Color.class).getBeanDefinition();

// 将bean的定义信息保存到BeanDefinitionRegistry中,在后续被BeanFactory获取到定义信息并创建对象
registry.registerBeanDefinition("newBean", rootBeanDefinition);
}

@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
// 其次执行
// 可以对beanFactory进行一些修改
System.out.println("====> postProcessBeanFactory ... bean的数量:" + beanFactory.getBeanDefinitionCount());
}
}

BeanDefinitionRegistryPostProcessor执行流程源码分析

  1. refresh()方法中调用invokeBeanFactoryPostProcessors()

image-20210705205828372

  1. 在其内的方法栈中先按照类型获取到postProcessorNames

image-20210709110018151

  1. 之后同样按照优先级依次执行invokeBeanDefinitionRegistryPostProcessors()(红色框)

image-20210709110448115

invokeBeanDefinitionRegistryPostProcessors():

image-20210709110356211

  1. 执行完invokeBeanDefinitionRegistryPostProcessors()后再执行invokeBeanFactoryPostProcessors()(黄色框)

image-20210709110448115

invokeBeanFactoryPostProcessors():

image-20210709110615151

注意:上述过程均在BeanFactoryPostProcessor组件的方法执行前执行

其与BeanFactoryPostProcessor执行时机对比

首先从容器中获取到所有的BeanDefinitionRegistryPostProcessor组件,依次触发其postProcessBeanDefinitionRegistry()方法,再触发postProcessBeanFactory()

之后再从容器中找到 BeanFactoryPostProcessor,并执行其postProcessBeanFactory()

即执行顺序:

  • BeanDefinitionRegistryPostProcessor.postProcessBeanDefinitionRegistry()
  • BeanDefinitionRegistryPostProcessor.postProcessBeanFactory()
  • BeanFactoryPostProcessor.postProcessBeanFactory()

Aware

1
2
3
4
5
6
7
8
9
10
/**
* A marker superinterface indicating that a bean is eligible to be notified by the
* Spring container of a particular framework object through a callback-style method.
* The actual method signature is determined by individual subinterfaces but should
* typically consist of just one void-returning method that accepts a single argument.
*
*/
public interface Aware {

}

Aware接口有若干继承的接口,命名格式为xxxAware:

image-20210630101718020

开发人员自定义的组件若想使用Spring底层的一些组件(如ApplicationContext、BeanFactory等),只需要实现相应的xxxAware(如ApplicationContextAware、BeanFactoryAware)接口,这些接口均继承自Aware接口,其特有的方法会以callback-style的方式被容器中对应的xxxAwareProcessor组件调用。

每个Aware接口实现类都对应了一个xxxAwareProcessor类(如ApplicationContextAware对应ApplicationContextAwareProcessor),该Processor类负责在容器中创建组件后(初始化之前)以回调的风格调用xxxAware实现类的特定方法(每个xxxAware实现类都有其特有的方法,功能都不同)。容器在逐一注册bean时,若发现某个bean实现了某个Aware接口,就会在容器中注册相应的xxxAwareProcessor类组件,让其负责回调该bean中实现的xxxAware接口的方法。

例如:ApplicationContextAware接口对应了一个ApplicationContextAwareProcessor类:

image-20210630102625001

image-20210630103554590

若开发人员自定义的某个bean(如下图中BookDao类)实现了ApplicationContextAware接口的setApplicationContext(ApplicationContext applicationContext)方法,则在容器加载BookDao类时,会根据其实现的ApplicationContextAware接口动态注册一个ApplicationContextAwareProcessor类。

image-20210630103106864

IoC容器在执行到方法栈AbstractAutowireCapableBeanFactory.java时,会遍历得到容器中所有的BeanPostProcessor,并一执行BeanPostProcessorpostProcessBeforeInitialization()方法,将bean对象逐一经过每个BeanPostProcessor处理器,此时会调用:

image-20210629164433894

ApplicationContextAwareProcessor类实现的postProcessBeforeInitialization()方法如下:

image-20210629192447682

每个bean在进入该方法后都会判断是否符合黄色框中接口的实现类,若符合(代表实现了xxxAware接口),则会执行invokeAwareInterfaces()方法,根据其实现的接口类型调用相应的方法设置相应的容器组件(红色框)。

image-20210630103302320 注意:在创建bean之前调用的invokeAwareMethods()方法(绿色框)内只会调用三个特殊的Aware接口实现类的方法,其他的Aware接口并不会在此执行,只能通过创建相应xxxAwareProcessor的方式回调执行相应方法。

image-20210630214340913

image-20210630213635404