springboot原理實戰(3)-- spring擴展接口BeanPostProcessor,BeanFactoryPostProcessor

目錄:

入門springboot前,先了解spring的下面這三個接口擴展,很有必要。
先看下腦圖:
在這裏插入圖片描述

1.BeanPostProcessor

這個接口上篇文章講過,spring利用這個接口,只要實現ApplicationContextWare接口,就可以在此接口,獲取springcontext.
他的主要作用也就是:在bean初始化時 搞點小動作:
舉例演示:
注入一個bean:

@Component
public class User {

    @PostConstruct
    public void init(){
        System.out.println("===user init==");
    }
}

實現BeanPostProcessor接口,這個接口會影響所有的bean初始化。

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

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("=========postProcessAfterInitialization========"+bean.getClass());

        return bean;
    }
}

測試:

public class App2 {
    public static void main(String[] args) {

        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext("com.springboot.demo3");
        System.out.println(User.class);
        context.close();
    }
}

運行結果:可以看出什麼?在bean初始化前後都打印了。
在這裏插入圖片描述

2.MyBeanFactoryPostProcessor

有了bean初始化時,進行一些小動作,那麼容器初始化時是不是可以做一些小動作呢?可以。
這個就是BeanFactoryPostProcessor接口。
BeanFactoryPostProcessor在spring容器初始化之後觸發,而且只會觸發一次.
我們實現下這個接口:

@Component
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        System.out.println("=================="+ beanFactory.getBeanDefinitionCount());
    }
}

運行結果:
在這裏插入圖片描述

顯示容器預先注入了8個對象,也就是,這個spring在背後注入了其他的bean。我們就可以在postProcessBeanFactory()方法中,在容器初始化時做一些業務操作。
特別注意: 僅僅會觸發一次這個方法。

3.BeanDefinitionRegistryPostProcessor

剛纔的那個方法,我們可以在容器初始化時,做一些事情,比如我們通過
beanFactory.getBeanDefinitionCount()獲取初始化bean的個數,但是能不能再這裏注入一些bean呢?
可以的。
不過得用到BeanFactoryPostProcessor的一個子接口:
在這裏插入圖片描述
這個類擴展了一個方法:
在這裏插入圖片描述
裏面有個參數BeanDefinitionRegistry.這個類可以幫我們注入一些bean的操作。
在這裏插入圖片描述
通過上面的registerBeanDefinition的方法。可以注入bean。
下面的removeBeanDefinition可以移除bean。
代碼演示:
我們實現這個BeanDefinitionRegistryPostProcessor接口注入10個Person對象:

public class Person {

    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                '}';
    }
}

注意Person沒有加@Component。
我們用容器注入:

@Component
public class MyBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {

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

    }

    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
        for (int i=1;i<=10;i++){
            BeanDefinitionBuilder bdb = BeanDefinitionBuilder.rootBeanDefinition(Person.class);
            bdb.addPropertyValue("name","admin"+i);
            registry.registerBeanDefinition("person"+i, bdb.getBeanDefinition());
        }
    }

}

測試類:

public class App2 {
    public static void main(String[] args) {

        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext("com.springboot.demo3");
        context.getBeansOfType(Person.class).values().forEach(System.out::println);
        context.close();
    }
}

打印結果:
在這裏插入圖片描述
顯示注入了。

擴展:也可以用AnnotationConfigApplicationContext注入

public class App2 {
    public static void main(String[] args) {

        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext("com.springboot.demo3");
        for (int i=1;i<=10;i++){
            BeanDefinitionBuilder bdb = BeanDefinitionBuilder.rootBeanDefinition(Person.class);
            bdb.addPropertyValue("name","admin"+i);
            context.registerBeanDefinition("person"+i, bdb.getBeanDefinition());
        }
        context.getBeansOfType(Person.class).values().forEach(System.out::println);
        context.close();
    }
}

運行結果:
在這裏插入圖片描述
爲什麼AnnotationConfigApplicationContext也可以注入bean呢?
在這裏插入圖片描述
在這裏插入圖片描述
通過觀察我們發現。AnnotationConfigApplicationContextBeanDefinitionRegistry子接口的子接口。所以可以調用BeanDefinitionRegistry的所有方法!!


個人微信公號:
搜索: 怒放de每一天
不定時推送相關文章,期待和大家一起成長!!
在這裏插入圖片描述


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