理解Spring中的BeanPostProcessor、BeanFactoryPostProcessor和BeanDefinitionRegistryPostProcessor

BeanPostProcessor: bean 後置處理器,bean 創建對象初始化前後進行攔截工作的
BeanFactoryPostProcessor: beanFactory 的後置處理器,在BeanFactory 標準初始化之後調用, 所有的 bean 定義 已經保存加載到 beanFactory 中, 但是 bean 的實例還沒有創建
BeanDefinitionRegistryPostProcessor:繼承於 BeanFactoryPostProcessor,postProcessBeanDefinitionRegistry()。在所有 bean 自定義信息將要被加載, bean 實例還未創建。 優先於 BeanFactoryPostProcessor 執行,利用 BeanDefinitionRegistryPostProcessor 給容器中添加一些組件

BeanPostProcessor.

BeanPostProcessor 中有兩個方法

public interface BeanPostProcessor {
    Object postProcessBeforeInitialization(Object var1, String var2) throws BeansException;

    Object postProcessAfterInitialization(Object var1, String var2) throws BeansException;
}

postProcessBeforeInitialization 方法在 bean對象的 init 方法之前執行。
postProcessAfterInitialization 方法在 bean 對象 init 方法之後執行

BeanPostProcessor

環境是 pom.xml中

<dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>4.3.12.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aspects</artifactId>
            <version>4.3.12.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-tx</artifactId>
            <version>4.3.12.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter-api</artifactId>
            <version>RELEASE</version>
            <scope>compile</scope>
        </dependency>

創建一個 bean 對象

@Component
public class Car {
    public Car(){
        System.out.println("car constructor ");
    }
    public void init(){
        System.out.println("car 。。。 init 。。。");
    }
    public void destory()
    {
        System.out.println("car .... destory");
    }
}

創建一個類來實現 BeanPostProcessor

@Component
public class MyBeanPostProcessor implements BeanPostProcessor {
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("postProcessBeforeInitialization:" + beanName +" bean : " + bean);
        return bean;
    }
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("postProcessAfterInitialization:" + beanName +" bean : " + bean);
        return bean;
    }
}

配置類

@Configuration
@ComponentScan({"cn.fllday.beans"})
public class MainConfigOfLifeCycle {
    @Bean(initMethod = "init",destroyMethod = "destory")
    public Car car(){
        return new Car();
    }
}

測試類

public class IOCTest_LifeCycle {
    @Test
    public void test01(){
        // 創建ioc容器
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MainConfigOfLifeCycle.class);
        System.out.println("容器創建完成");
        context.close();
    }
}

我們打斷點執行,查看執行語句

car constructor 
postProcessBeforeInitialization:car bean : cn.fllday.beans.Car@258d79be
car 。。。 init 。。。
postProcessAfterInitialization:car bean : cn.fllday.beans.Car@258d79be
  1. 先執行 構造器,
  2. 然後執行postProcessBeforeInitialization
  3. 再次執行 init 方法,
  4. 在執行postProcessAfterInitialization 方法
  5. 每一個單例 bean 都會執行一遍

BeanDefinitionRegistryPostProcessor

  1. 在所有 bean 自定義信息將要被加載, bean 實例還未創建
  2. 優先於 BeanFactoryPostProcessor 執行,
  3. 利用 BeanDefinitionRegistryPostProcessor 給容器中添加一些組件

還是剛纔的例子 。 我們創建一個ExtBeanDefinitionRegistryPostProcessor.java

@Component
public class ExtBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {

    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry beanDefinitionRegistry) throws BeansException {
        System.out.println("ExtBeanDefinitionRegistryPostProcessor.postProcessBeanDefinitionRegistry。。。bean的數量: " + beanDefinitionRegistry.getBeanDefinitionCount());
        RootBeanDefinition car = new RootBeanDefinition(Car.class);
        beanDefinitionRegistry.registerBeanDefinition("person",car);
    }

    public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
        System.out.println("ExtBeanDefinitionRegistryPostProcessor.ExtBeanDefinitionRegistryPostProcessor 。。。 bean的數量:" + configurableListableBeanFactory.getBeanDefinitionCount());
    }
}

beanDefinitionRegistry bean 定義信息的保存中心,以後 beanFactory 就是按照 BeanDefinitionRegistry 裏面保存的每一個bean 定義信息創建bean 實例
再次運行 剛剛的測試方法

ioc 容器開始初始化
312, 2020 1:58:13 下午 org.springframework.context.annotation.AnnotationConfigApplicationContext prepareRefresh
信息: Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@29f69090: startup date [Thu Mar 12 13:58:13 CST 2020]; root of context hierarchy
ExtBeanDefinitionRegistryPostProcessor.postProcessBeanDefinitionRegistry。。。bean的數量: 9
WARNING: An illegal reflective access operation has occurred
WARNING: Illegal reflective access by org.springframework.cglib.core.ReflectUtils$1 (file:/C:/Users/gssznb/.m2/repository/org/springframework/spring-core/4.3.12.RELEASE/spring-core-4.3.12.RELEASE.jar) to method java.lang.ClassLoader.defineClass(java.lang.String,byte[],int,int,java.security.ProtectionDomain)
WARNING: Please consider reporting this to the maintainers of org.springframework.cglib.core.ReflectUtils$1
WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations
WARNING: All illegal access operations will be denied in a future release
ExtBeanDefinitionRegistryPostProcessor.ExtBeanDefinitionRegistryPostProcessor 。。。 bean的數量:10
postProcessBeforeInitialization:org.springframework.context.event.internalEventListenerProcessor bean : org.springframework.context.event.EventListenerMethodProcessor@275bf9b3
postProcessAfterInitialization:org.springframework.context.event.internalEventListenerProcessor bean : org.springframework.context.event.EventListenerMethodProcessor@275bf9b3
postProcessBeforeInitialization:org.springframework.context.event.internalEventListenerFactory bean : org.springframework.context.event.DefaultEventListenerFactory@12a94400
postProcessAfterInitialization:org.springframework.context.event.internalEventListenerFactory bean : org.springframework.context.event.DefaultEventListenerFactory@12a94400
postProcessBeforeInitialization:extConfig bean : cn.fllday.config.ExtConfig$$EnhancerBySpringCGLIB$$31ab2d3@5495333e
postProcessAfterInitialization:extConfig bean : cn.fllday.config.ExtConfig$$EnhancerBySpringCGLIB$$31ab2d3@5495333e
car constructor 
postProcessBeforeInitialization:car bean : cn.fllday.beans.Car@b978d10
car 。。。 init 。。。
postProcessAfterInitialization:car bean : cn.fllday.beans.Car@b978d10
car constructor 
postProcessBeforeInitialization:person bean : cn.fllday.beans.Car@5b7a8434
postProcessAfterInitialization:person bean : cn.fllday.beans.Car@5b7a8434
ioc 容器創建完成
312, 2020 1:59:32 下午 org.springframework.context.annotation.AnnotationConfigApplicationContext doClose
信息: Closing org.springframework.context.annotation.AnnotationConfigApplicationContext@29f69090: startup date [Thu Mar 12 13:58:13 CST 2020]; root of context hierarchy
car .... destory

**我們看到postProcessBeanDefinitionRegistry先執行,然後通過該方法,定義了一個bean,未定義的時候, bean的數量爲9, 在使用postProcessBeanFactory,發現bean 有 10 個。隨後在執行了。 構造方法,BeanPostProcessor類的 postProcessBeforeInitialization(),bean的init() 和 postProcessAfterInitialization() **

BeanFactoryPostProcessor

創建一個 BeanFactoryPostProcessor 類
ExtBeanFactoryPostProcessor.java

@Component
public class ExtBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        System.out.println("beanFacotry 執行");
        int beanDefinitionCount = beanFactory.getBeanDefinitionCount();
        System.out.println("查看當前容器中擁有 " + beanDefinitionCount + "個bean");
        String[] beanDefinitionNames = beanFactory.getBeanDefinitionNames();
        for (String name:beanDefinitionNames){
            System.out.println("beanFactory 執行 ------------------------: " + name+",  ");
        }
        System.out.println();
        Car bean = (Car) beanFactory.getBean("car");
        System.out.println(bean);
        System.out.println("執行完成");
    }
}

運行 剛纔的測試方法
打印結果

ioc 容器開始初始化
312, 2020 11:52:06 上午 org.springframework.context.annotation.AnnotationConfigApplicationContext prepareRefresh
信息: Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@573f2bb1: startup date [Thu Mar 12 11:52:06 CST 2020]; root of context hierarchy
ExtBeanDefinitionRegistryPostProcessor.postProcessBeanDefinitionRegistry。。。bean的數量: 10
WARNING: An illegal reflective access operation has occurred
WARNING: Illegal reflective access by org.springframework.cglib.core.ReflectUtils$1 (file:/C:/Users/gssznb/.m2/repository/org/springframework/spring-core/4.3.12.RELEASE/spring-core-4.3.12.RELEASE.jar) to method java.lang.ClassLoader.defineClass(java.lang.String,byte[],int,int,java.security.ProtectionDomain)
WARNING: Please consider reporting this to the maintainers of org.springframework.cglib.core.ReflectUtils$1
WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations
WARNING: All illegal access operations will be denied in a future release
ExtBeanDefinitionRegistryPostProcessor.ExtBeanDefinitionRegistryPostProcessor 。。。 bean的數量:11
beanFacotry 執行
查看當前容器中擁有 11個bean
beanFactory 執行 ------------------------: org.springframework.context.annotation.internalConfigurationAnnotationProcessor,  
beanFactory 執行 ------------------------: org.springframework.context.annotation.internalAutowiredAnnotationProcessor,  
beanFactory 執行 ------------------------: org.springframework.context.annotation.internalRequiredAnnotationProcessor,  
beanFactory 執行 ------------------------: org.springframework.context.event.internalEventListenerProcessor,  
beanFactory 執行 ------------------------: org.springframework.context.event.internalEventListenerFactory,  
beanFactory 執行 ------------------------: extConfig,  
beanFactory 執行 ------------------------: extBeanDefinitionRegistryPostProcessor,  
beanFactory 執行 ------------------------: extBeanFactoryPostProcessor,  
beanFactory 執行 ------------------------: myBeanPostProcessor,  
beanFactory 執行 ------------------------: car,  
beanFactory 執行 ------------------------: person,  

car constructor 
cn.fllday.beans.Car@68267da0
執行完成
postProcessBeforeInitialization:org.springframework.context.event.internalEventListenerProcessor bean : org.springframework.context.event.EventListenerMethodProcessor@f381794
postProcessAfterInitialization:org.springframework.context.event.internalEventListenerProcessor bean : org.springframework.context.event.EventListenerMethodProcessor@f381794
postProcessBeforeInitialization:org.springframework.context.event.internalEventListenerFactory bean : org.springframework.context.event.DefaultEventListenerFactory@2e1d27ba
postProcessAfterInitialization:org.springframework.context.event.internalEventListenerFactory bean : org.springframework.context.event.DefaultEventListenerFactory@2e1d27ba
car constructor 
postProcessBeforeInitialization:person bean : cn.fllday.beans.Car@61d6015a
postProcessAfterInitialization:person bean : cn.fllday.beans.Car@61d6015a
ioc 容器創建完成

可以看到最先執行的還是BeanDefinitionRegistryPostProcessor.postProcessBeanDefinitionRegistry(),然後執行BeanDefinitionRegistryPostProcessor.ExtBeanDefinitionRegistryPostProcessor(),再然後BeanFactoryPostProcessor.postProcessBeanFactory(), 執行完之後,在開始創建bean 實例。 先執行 構造方法。然後BeanPostProcessor.postProcessBeforeInitialization()方法,再次執行 postProcessAfterInitialization()方法。在執行BeanFactoryProcessor的時候我們從 beanFactory中拿到了 car 實例。那麼 car 實例會被提前創建出來。執行 構造方法和 init 方法,但是並不會執行BeanPostProcessor中的postProcessBeforeInitialization方法和 postProcessAfterInitialization方法。當再次創建bean 實例的時候, 只會執行構造方法和 BeanPostProcessor中的postProcessBeforeInitialization方法和 postProcessAfterInitialization方法,init方法並不會執行

結束: 看到的小夥伴發現有問題 ,希望指正

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章