首先,咱们来看一下BeanDefinitionRegistryPostProcessor的源码,如下图所示。
从该接口的名字中,我们大概能知道个一二,说它是bean定义注册中心的后置处理器并不过分。而且,从该接口的源码中我们也可以看出,它是BeanFactoryPostProcessor旗下的一个子接口。
我们还能看到,它里面定义了一个方法,叫postProcessBeanDefinitionRegistry,那么问题来了,它是什么时候执行的呢?我们可以看一下它上面的详细描述,说的是啥呢,说的是在IOC容器标准初始化之后,允许我们来修改IOC容器里面的bean定义注册中心。此时,所有合法的bean定义将要被加载,但是这些bean还没有初始化完成。
说人话就是,postProcessBeanDefinitionRegistry方法的执行时机是在所有bean定义信息将要被加载,但是bean实例还未创建的时候。 这句话听起来,总感觉BeanDefinitionRegistryPostProcessor是在BeanFactoryPostProcessor前面执行的,真的是这样吗?确实是这样。为什么呢?BeanFactoryPostProcessor的执行时机是在所有的bean定义信息已经保存加载到BeanFactory中之后,而BeanDefinitionRegistryPostProcessor却是在所有的bean定义信息将要被加载的时候,所以,BeanDefinitionRegistryPostProcessor就应该要先来执行。接下来,我们就写一个实践案例来验证一番。
案例实践
首先,编写一个类,例如MyBeanDefinitionRegistryPostProcessor,它应要实现BeanDefinitionRegistryPostProcessor这个接口。
package com.baidu.bean;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
import org.springframework.stereotype.Component;
// 记住,我们这个组件写完之后,一定别忘了给它加在容器中
@Component
public class MyBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
// TODO Auto-generated method stub
System.out.println("MyBeanDefinitionRegistryPostProcessor...bean的数量:" + beanFactory.getBeanDefinitionCount());
}
/**
* 这个BeanDefinitionRegistry就是Bean定义信息的保存中心,这个注册中心里面存储了所有的bean定义信息,
* 以后,BeanFactory就是按照BeanDefinitionRegistry里面保存的每一个bean定义信息来创建bean实例的。
*
* bean定义信息包括有哪些呢?有这些,这个bean是单例的还是多例的、bean的类型是什么以及bean的id是什么。
* 也就是说,这些信息都是存在BeanDefinitionRegistry里面的。
*/
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
// TODO Auto-generated method stub
System.out.println("postProcessBeanDefinitionRegistry...bean的数量:" + registry.getBeanDefinitionCount());
// 除了查看bean的数量之外,我们还可以给容器里面注册一些bean,我们以前也简单地用过
/*
* 第一个参数:我们将要给容器中注册的bean的名字
* 第二个参数:BeanDefinition对象
*/
// RootBeanDefinition beanDefinition = new RootBeanDefinition(Blue.class); // 现在我准备给容器中添加一个Blue对象
// 咱们也可以用另外一种办法,即使用BeanDefinitionBuilder这个构建器生成一个BeanDefinition对象,很显然,这两种方法的效果都是一样的
AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.rootBeanDefinition(Blue.class).getBeanDefinition();
registry.registerBeanDefinition("hello", beanDefinition);
}
}
咱们编写的类实现BeanDefinitionRegistryPostProcessor接口之后,还得来实现两个方法,第一个方法,即postProcessBeanFactory,它来源于BeanFactoryPostProcessor接口里面定义的方法;第二个方法,即postProcessBeanDefinitionRegistry,它来源于BeanDefinitionRegistryPostProcessor接口里面定义的方法。
接下来,我们就来测试一下以上类里面的两个方法是什么时候执行的。运行IOCTest_Ext测试类中的test01方法,可以看到Eclipse控制台打印了如下内容。
可以看到,是我们自己写的MyBeanDefinitionRegistryPostProcessor类里面的postProcessBeanDefinitionRegistry方法先执行,该方法具体都做了哪些事呢?它先是拿到IOC容器中bean的数量(即10),再是向IOC容器中注册一个组件。接着,是我们自己写的MyBeanDefinitionRegistryPostProcessor类里面的postProcessBeanFactory方法再执行,该方法只是打印了一下IOC容器中bean的数量。你不仅要问了,为什么打印出的IOC容器中bean的数量是11,而不是10呢?这是因为我们之前已经向IOC容器中注册了一个组件。
除此之外,从Eclipse控制台输出的结果中我们还能看到,我们自己写的MyBeanDefinitionRegistryPostProcessor类里面的方法都执行完了以后,才轮到外面那些BeanFactoryPostProcessor来执行,执行的时候,不仅输出了IOC容器中bean的数量,而且还输出了每一个bean定义的名字。
现在我们是不是可以得出这样一个结论,BeanDefinitionRegistryPostProcessor是优先于BeanFactoryPostProcessor执行的,而且我们可以利用它给容器中再额外添加一些组件。
小结:
- 创建IOC容器
- 创建IOC容器时,要调用一个刷新方法,即refresh方法
- 从IOC容器中获取到所有的BeanDefinitionRegistryPostProcessor组件,并依次触发它们的postProcessBeanDefinitionRegistry方法,然后再来触发它们的postProcessBeanFactory方法
- 再来从IOC容器中获取到所有的BeanFactoryPostProcessor组件,并依次触发它们的postProcessBeanFactory方法
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/71815.html