上一篇我们介绍到obtainFreshBeanFactory
本文将介绍 obtainFreshBeanFactory 方法之后的另一个重要方法——invokeBeanFactoryPostProcessors。
本方法会实例化和调用所有 BeanFactoryPostProcessor(包括其子类 BeanDefinitionRegistryPostProcessor)。
BeanFactoryPostProcessor 接口是 Spring 初始化 BeanFactory 时对外暴露的扩展点,Spring IoC 容器允许 BeanFactoryPostProcessor 在容器实例化任何 bean 之前读取 bean 的定义,并可以修改它。
BeanDefinitionRegistryPostProcessor 继承自 BeanFactoryPostProcessor,比 BeanFactoryPostProcessor 具有更高的优先级,主要用来在常规的 BeanFactoryPostProcessor 检测开始之前注册其他 bean 定义。特别是,你可以通过 BeanDefinitionRegistryPostProcessor 来注册一些常规的 BeanFactoryPostProcessor,因为此时所有常规的 BeanFactoryPostProcessor 都还没开始被处理。
注:这边的 “常规 BeanFactoryPostProcessor” 主要用来跟 BeanDefinitionRegistryPostProcessor 区分。
okay 首先我们来到invokeBeanFactoryPostProcessors(beanFactory) 方法,点击进去:
1.拿到当前应用上下文 beanFactoryPostProcessors 变量中的值,见代码块1详解。
2.实例化并调用所有已注册的 BeanFactoryPostProcessor,见代码块2详解。
这里getBeanFactoryPostProcessors() 会拿到当前应用上下文中已经注册的 BeanFactoryPostProcessor,在默认情况下,this.beanFactoryPostProcessors 是返回空的。
那么如果我们自己想添加一个BeanFactoryPostProcessor到beanFactory中应该怎么做。。ok
我们可以在refresh方法之前去添加一个自定义的BeanFactoryPostProcessor 到容器中,通常来讲有两种方式,,
如下:
1.通过注解的方式,将自己实现的beanFactoryPostProcessor注册到beanFactory中,,
可以看到在invokeBeanFactoryPostProcessors方法中我们就可以取到自定义的beanFactoryPostProcessor
2.新建一个 ApplicationContextInitializer 的实现类 SpringApplicationContextInitializer ,并在 initialize 方法中写我们的逻辑,
(此时我们是通过web容器初始化的时候去做的添加,,,就要把Component去掉了) 如下:
将 SpringApplicationContextInitializer 作为初始化参数 contextInitializerClasses 配置到 web.xml 中
这样,在启动应用时,FirstBeanDefinitionRegistryPostProcessor 就会被添加到 this.beanFactoryPostProcessors 中。
1.判断 beanFactory 是否为 BeanDefinitionRegistry。beanFactory 是在之前的 obtainFreshBeanFactory 方法构建的,具体代码在:AbstractRefreshableApplicationContext.refreshBeanFactory() 方法,代码如下。
@Override
protected final void refreshBeanFactory() throws BeansException {
if (hasBeanFactory()) {
destroyBeans();
closeBeanFactory();
}
try {
// 创建一个新的BeanFactory
DefaultListableBeanFactory beanFactory = createBeanFactory();
beanFactory.setSerializationId(getId());
customizeBeanFactory(beanFactory);
loadBeanDefinitions(beanFactory);
synchronized (this.beanFactoryMonitor) {
this.beanFactory = beanFactory;
}
}
catch (IOException ex) {
throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
}
}
可以看出,我们构建的 beanFactory 是一个 DefaultListableBeanFactory ,而 DefaultListableBeanFactory 实现了BeanDefinitionRegistry 接口,因此 beanFactory instanceof BeanDefinitionRegistry 结果为 true。
3.4 获取 ppName 对应的 bean 实例,添加到 currentRegistryProcessors 中,准备执行。beanFactory.getBean 方法会触发创建 ppName 对应的 bean 实例对象,创建 bean 实例是 IoC 的另一个核心内容,目前暂不深入解析。
3.6 进行排序,该方法在下面也被调用了好几次,见代码块3详解。
默认情况下,比较器为 OrderComparator;如果配置了 annotation-config,并且值为true,使用的是 AnnotationAwareOrderComparator,AnnotationAwareOrderComparator 继承自 OrderComparator,只是重写了部分方法,比较器的部分代码如下:
@Override
public int compare(Object o1, Object o2) {
return doCompare(o1, o2, null);
}
private int doCompare(Object o1, Object o2, OrderSourceProvider sourceProvider) {
// 判断o1是否实现了PriorityOrdered接口
boolean p1 = (o1 instanceof PriorityOrdered);
// 判断o2是否实现了PriorityOrdered接口
boolean p2 = (o2 instanceof PriorityOrdered);
// 1.如果o1实现了PriorityOrdered接口, 而o2没有, 则o1排前面
if (p1 && !p2) {
return -1;
}
// 2.如果o2实现了PriorityOrdered接口, 而o1没有, 则o2排前面
else if (p2 && !p1) {
return 1;
}
// 3.如果o1和o2都实现(都没实现)PriorityOrdered接口
// Direct evaluation instead of Integer.compareTo to avoid unnecessary object creation.
// 拿到o1的order值, 如果没实现Ordered接口, 值为Ordered.LOWEST_PRECEDENCE
int i1 = getOrder(o1, sourceProvider);
// 拿到o2的order值, 如果没实现Ordered接口, 值为Ordered.LOWEST_PRECEDENCE
int i2 = getOrder(o2, sourceProvider);
// 4.通过order值(order值越小, 优先级越高)排序
return (i1 < i2) ? -1 : (i1 > i2) ? 1 : 0;
}
比较器的逻辑很简单,实现 PriorityOrdered 接口的优先级最高,如果两个对象都实现(都没实现)PriorityOrdered 接口,则根据 order 值(实现 Ordered 接口时,需要实现 getOrder() 方法,返回 order 值)来进行比较,order 值越小,优先级越高。
BeanDefinitionRegistryPostProcessor 和BeanFactoryPostProcessor一样,想要扩展使用,就把对应自己实现的processor添加到容器中即可,BeanDefinitionRegistryPostProcessor会多出一个方法postProcessBeanDefinitionRegistry,,这个方法可以注册一个beanDefinition 到容器中,是一个很强大的功能。。。。
实例:
Mybatis扩展spring时,经常用到的 org.mybatis.spring.mapper.MapperScannerConfigurer
其实就是一个BeanDefinitionRegistryPostProcessor。MapperScannerConfigurer 在 postProcessBeanDefinitionRegistry 方法中进行了一些操作,主要是:扫描 basePackage 指定的目录,将该目录下的类(通常是 DAO/MAPPER 接口)封装成 BeanDefinition 并加载到 BeanFactory 中,后期可以直接初始化到容器中。。。因此,我们可以看到我们项目中的 DAO(MAPPER)接口,通常都没有使用注解或 XML 的方式注册到 Spring 容器,但是我们还是可以在 Service 服务中,使用 @Autowire 注解来将其注入到 Service 中,就是因为这个原因。配置如下:
invokeBeanFactoryPostProcessors 内容比较多,,需要大家慢慢啃。。大概的逻辑如下:
1.整个 invokeBeanFactoryPostProcessors 方法围绕两个接口,BeanDefinitionRegistryPostProcessor 和 BeanFactoryPostProcessor,其中 BeanDefinitionRegistryPostProcessor 继承了 BeanFactoryPostProcessor 。BeanDefinitionRegistryPostProcessor 主要用来在常规 BeanFactoryPostProcessor 检测开始之前注册其他 Bean 定义,说的简单点,就是 BeanDefinitionRegistryPostProcessor 具有更高的优先级,执行顺序在 BeanFactoryPostProcessor 之前。
2.整个 invokeBeanFactoryPostProcessors 方法操作了 3 种 bean 对象:
入参 beanFactoryPostProcessors:
这个我们在代码块1中解析过,拿的是 AbstractApplicationContext 类的 beanFactoryPostProcessors 属性值,也就是在之前已经添加到 beanFactoryPostProcessors 中的 BeanFactoryPostProcessor。
BeanDefinitionRegistryPostProcessor 接口实现类:
实现了 BeanDefinitionRegistryPostProcessor 接口,并且注册到 Spring IoC容器中。
常规 BeanFactoryPostProcessor 接口实现类:
实现了 BeanFactoryPostProcessor 接口,并且注册到 Spring IoC容器中。
3. 操作3种 bean 对象具体指的是调用它们重写的方法,调用实现方法时会遵循以下的优先级:
第一优先级:入参 beanFactoryPostProcessors 中的 BeanDefinitionRegistryPostProcessor, 调用 postProcessBeanDefinitionRegistry 方法(2.1.1)。
第二优先级:BeanDefinitionRegistryPostProcessor 接口实现类,并且实现了 PriorityOrdered 接口,调用 postProcessBeanDefinitionRegistry 方法(3.8)。
第三优先级:BeanDefinitionRegistryPostProcessor 接口实现类,并且实现了 Ordered 接口,调用 postProcessBeanDefinitionRegistry 方法(4.2)。
第四优先级:除去第二优先级和第三优先级,剩余的 BeanDefinitionRegistryPostProcessor 接口实现类,调用 postProcessBeanDefinitionRegistry 方法(5.4)。
第五优先级:所有 BeanDefinitionRegistryPostProcessor 接口实现类,调用 postProcessBeanFactory 方法(6)。
第六优先级:入参 beanFactoryPostProcessors 中的常规 BeanFactoryPostProcessor,调用 postProcessBeanFactory 方法(7)。
第七优先级:常规 BeanFactoryPostProcessor 接口实现类,并且实现了 PriorityOrdered 接口,调用 postProcessBeanFactory 方法(9.2)。
第八优先级:常规 BeanFactoryPostProcessor 接口实现类,并且实现了 Ordered 接口,调用 postProcessBeanFactory 方法(10.3)。
第九优先级:除去第七优先级和第八优先级,剩余的常规 BeanFactoryPostProcessor 接口的实现类,调用 postProcessBeanFactory 方法(11.2)。