0
点赞
收藏
分享

微信扫一扫

BeanFactoryPostProcessor的调用时机

乐百川 2022-05-05 阅读 91
java

BeanFactoryPostProcessor的调用时机

BeanFactoryPostProcessor其实就是BeanFactory(创建bean的工厂)的后置处理器。说起这个,你脑海中是不是泛起了回忆,是不是想起了有一个与BeanFactoryPostProcessor的名字极其相似的玩意,它就是BeanPostProcessor。那什么是BeanPostProcessor呢?我们之前早就说过了,它就是bean的后置处理器,并且是在bean创建对象初始化前后进行拦截工作的。

现在我们要讲解的是BeanFactoryPostProcessor,上面也说过了,它是BeanFactory(创建bean的工厂)的后置处理器。接下来,我们就要搞清楚它的内部原理了,想要搞清楚其内部原理,我们需要从它是什么时候工作这一点开始入手研究,也即搞清楚它的调用时机是什么。

我们点进去BeanFactoryPostProcessor的源码里面去看一看,发现它是一个接口,如下图所示。
在这里插入图片描述
仔细看一下其内部postProcessBeanFactory方法上的描述,这很重要,因为从这段描述中我们就可以知道BeanFactoryPostProcessor的调用时机。描述中说,我们可以在IOC容器里面的BeanFactory的标准初始化完成之后,修改IOC容器里面的这个BeanFactory。

也就是说,BeanFactoryPostProcessor的调用时机是在BeanFactory标准初始化之后,这样一来,我们就可以来定制和修改BeanFactory里面的一些内容了。那什么叫标准初始化呢?接着看描述,它说的是所有的bean定义已经被加载了,但是还没有bean被初始化。

说人话,就是BeanFactoryPostProcessor的调用时机是在BeanFactory标准初始化之后,这样一来,我们就可以来定制和修改BeanFactory里面的一些内容了,此时,所有的bean定义已经保存加载到BeanFactory中了,但是bean的实例还未创建。

案例实践

接下来,我们来编写一个案例来验证一下以上说的内容。

首先,我们来编写一个我们自己的BeanFactoryPostProcessor,例如MyBeanFactoryPostProcessor。要编写这样一个bean工厂的后置处理器,它得需要实现我们上面说的BeanFactoryPostProcessor接口,并且还得添加一个实现方法。由于BeanFactoryPostProcessor接口里面只声明了一个方法,即postProcessBeanFactory,所以咱们自己编写的MyBeanFactoryPostProcessor类中只需要实现其即可。

package com.baidu.bean;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.stereotype.Component;

import java.util.Arrays;

@Component
public class MainBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
    /**
     * Modify the application context's internal bean factory after its standard
     * initialization. All bean definitions will have been loaded, but no beans
     * will have been instantiated yet. This allows for overriding or adding
     * properties even to eager-initializing beans.
     *
     * @param beanFactory the bean factory used by the application context
     * @throws BeansException in case of errors
     */

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {

        System.out.println("MyBeanFactoryPostProcessor...postProcessBeanFactory..."); // 这个时候我们所有的bean还没被创建
        // 但是我们可以看一下通过Spring给我们传过来的这个beanFactory,我们能拿到什么

        int count = beanFactory.getBeanDefinitionCount(); // 我们能拿到有几个bean定义
        String[] names = beanFactory.getBeanDefinitionNames(); // 除此之外,我们还能拿到每一个bean定义的名字

        System.out.println("当前BeanFactory中有" + count + "个Bean");
        System.out.println(Arrays.asList(names));

    }

}

注意,我们自己编写的MyBeanFactoryPostProcessor类要想让Spring知道,并且还要能被使用起来,那么它一定就得被加在容器中,为此,我们可以在其上标注一个@Component注解。

然后,创建一个配置类,例如ExtConfig,记得还要在该配置类上使用@ComponentScan注解来配置包扫描哟!

当然了,我们也可以使用@Bean注解向容器中注入咱自己写的组件,例如,在这里,我们可以向容器中注入一个Blue组件。

package com.baidu.config;

import com.baidu.bean.Blue;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;


@ComponentScan("com.baidu.bean")
@Configuration
public class ExtFactoryPostConfig {

   @Bean
   public Blue blue(){
       return new Blue();
   }

}

上面这个Blue组件其实就是一个非常普通的组件,代码如下所示:

package com.baidu.bean;

public class Blue {
    public Blue() {
        System.out.println("Blue-->无参的构造方法");
    }

    public void init(){
        System.out.println("Blue...init.....");
    }

    public void destory(){
        System.out.println("Blue...destory....");
    }
}

可以看到,在创建Blue对象的时候,无参构造器会有相应打印。

接着,编写一个单元测试类,例如IOCTest_Ext,来进行测试。


    @Test
    public void test01(){
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ExtFactoryPostConfig.class);

        //关闭容器
        context.close();

    }

测试啥呢?其实就是来验证一下BeanFactoryPostProcessor的调用时机。说得更具体一点就是,就是看一下咱们自己编写的BeanFactoryPostProcessor究竟是不是在所有的bean定义已经被加载,但是还未创建对象的时候工作?

那咱们接下来就来一探究竟。运行IOCTest_Ext类中的test01方法,可以看到Eclipse控制台打印出了如下内容。

哎呀!咱们自己编写的BeanFactoryPostProcessor在Blue类的无参构造器创建Blue对象之前就已经工作了。细心一点看的话,从bean的定义信息中还能看到Blue组件注册到容器中的名字,只是此刻还没创建对象,如下图所示。
在这里插入图片描述
说明BeanFactoryPostProcessor是在所有的bean定义信息都被加载之后才调用的。

https://liayun.blog.csdn.net/article/details/113103870

举报

相关推荐

0 条评论