初步认识一下BeanDefinitionRegistryPostProcessor

首先,咱们来看一下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://liayun.blog.csdn.net/article/details/113781809

  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值