spring注解驱动开发-(13)-三个PostProcessor

  1. 1. BeanPostProcessor
  2. 2. BeanFactoryPostProcessor
  3. 3. BeanDefinitionRegistryPostProcessor
  4. 4. 执行顺序解析
  5. 5. 小结

大致整理下面这些类的作用和关系:

BeanPostProcessor Bean初始化的后置处理器;
BeanFactoryPostProcessor BeanFactory的后置处理器;
BeanDefinitionRegistryPostProcessorBeanFactoryPostProcessor的子接口, 新增了一个方法!

1. BeanPostProcessor

Bean初始化的后置处理器
postProcessBeforeInitialization() 在bean初始化前执行;
postProcessAfterInitialization() 在bean初始化完成后执行;

BeanPostProcessor 默认是会对整个Spring容器中所有的bean进行处理; 可以根据参数 bean和 beanName做一些选择和拦截操作, 比如为某个bean设一个值;

package com.niewj.util;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.stereotype.Component;

/**
 * 通过 BeanPostProcessor 接口
 */
@Component
public class MyBeanPostProcessor implements BeanPostProcessor {

    public MyBeanPostProcessor() {
        System.out.println("MyBeanPostProcessor-初始化!");
    }

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        // 可以通过此方法, 找到某一个目标 bean, 做一些操作: 如给容器中的 Service1 依赖的空对象赋值
        // 注意: 这里的 Service1.setService2(new Service2()) 中的 Service2 不会注册到容器中!
        // 但是 在Service1中使用 Service2的方法时, 是有我们赋值的对象的;
        System.out.println("###->MyBeanPostProcessor#postProcessBeforeInitialization->beanName=[" + beanName + "]###-> begin");
        if (bean instanceof Service1) {
            Service1 service1 = (Service1) bean;
            System.out.println("bean=" + bean + "; bean依赖为: " + service1.getService2());
            // 注入依赖(自己new的)
            service1.setService2(new Service2());
        }
        System.out.println("###->MyBeanPostProcessor#postProcessBeforeInitialization->beanName=[" + beanName + "]###-> end");
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        // 由于上面已经赋值, 这里可以拿到
        System.out.println("###->MyBeanPostProcessor#postProcessAfterInitialization->beanName=[" + beanName + "]###-> begin");
        if (bean instanceof Service1) {
            Service1 service1 = (Service1) bean;
            System.out.println("bean=" + bean + "; bean依赖为: " + service1.getService2());
        }
        System.out.println("###->MyBeanPostProcessor#postProcessAfterInitialization->beanName=[" + beanName + "]###-> end");
        return bean;
    }
}

2. BeanFactoryPostProcessor

相比较 BeanPostProcessor, 它是针对 BeanFactory的;

BeanFactoryPostProcessor的执行时机是: 在Bean定义保存加载完成, bean尚未初始化前执行;

要先于 BeanPostProcessor的两个方法;

但是要晚于 BeanDefinitionRegistryPostProcessor 的另一个方法: postProcessBeanDefinitionRegistry()

具体参见 BeanDefinitionRegistryPostProcessor

package com.niewj.util;

import org.springframework.beans.BeansException;
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 MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        System.out.println("===> MyBeanFactoryPostProcessor#postProcessBeanFactory-->可以获取容器内bean定义的数量->getBeanDefinitionCount=> " + beanFactory.getBeanDefinitionCount());
        System.out.println("===> MyBeanFactoryPostProcessor#postProcessBeanFactory-->可以打印容器中的所有 定义的BeanDefinition->getBeanDefinitionNames:");
        System.out.println(Arrays.asList(beanFactory.getBeanDefinitionNames()));
    }
}

3. BeanDefinitionRegistryPostProcessor

BeanDefinitionRegistryPostProcessor 是上面 BeanFactoryPostProcessor 的子接口;

它除了有方法 postProcessBeanFactory()之外, 自己还新增了一个方法 postProcessBeanDefinitionRegistry

他们的执行时机:

postProcessBeanDefinitionRegistry()方法的执行时机是: 容器中所有的bean定义将要被加载前! 可以获取到 bean定义的注册器, 可用于注册bean;

postProcessBeanFactory() 方法的执行时机是: 容器中所有的bean已经保存加载, 但bean还未创建! 可以用来从beanFactory中拿出 bean;

package com.niewj.util;

import com.niewj.bean.Pojo4;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.config.BeanDefinition;
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;

import java.util.Arrays;

@Component
public class MyBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {
    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
        System.out.println("===> MyBeanDefinitionRegistryPostProcessor#postProcessBeanDefinitionRegistry 调用!!!");
        System.out.println("registry instanceof BeanFactory: " + (registry instanceof BeanFactory));

        System.out.println("###->MyBeanDefinitionRegistryPostProcessor注册bean:[Service2.class]###-> begin");
        // 注册一个bean: Service2(并没有注解 @Component)
        AbstractBeanDefinition myBean = BeanDefinitionBuilder.rootBeanDefinition(Service2.class).getBeanDefinition();
        registry.registerBeanDefinition("service2", myBean);
        System.out.println("###->MyBeanDefinitionRegistryPostProcessor注册bean:[Service2.class]###-> over");

        System.out.println("###->MyBeanDefinitionRegistryPostProcessor注册bean:[Pojo4.class]###-> begin");
        // 注册一个bean: Pojo4
        AbstractBeanDefinition myPojo4 = BeanDefinitionBuilder.rootBeanDefinition(Pojo4.class).getBeanDefinition();
        registry.registerBeanDefinition("myPojo4", myPojo4);
        System.out.println("###->MyBeanDefinitionRegistryPostProcessor注册bean:[Pojo4.class]###-> over");
    }

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        // 1. 可以再次修改容器内一些bean的特征: 如设置 Pojo4类延迟初始化!
        BeanDefinition myPojo4 = beanFactory.getBeanDefinition("myPojo4");
        myPojo4.setLazyInit(true);

        // 2. 可以获取容器内bean定义的数量
        System.out.println("===> MyBeanDefinitionRegistryPostProcessor#postProcessBeanFactory-->可以获取容器内bean定义的数量->getBeanDefinitionCount=> " + beanFactory.getBeanDefinitionCount());

        // 3. 可以打印容器中的所有 定义的BeanDefinition
        System.out.println("===> MyBeanDefinitionRegistryPostProcessor#postProcessBeanFactory-->可以打印容器中的所有 定义的BeanDefinition->getBeanDefinitionNames:\t");
        System.out.println(Arrays.asList(beanFactory.getBeanDefinitionNames()));
    }
}

像本例中 Test2Service 并未注解 @Component/@Service等; 通过注册器可以将普通bean注册到容器:

BeanDefinitionBuilder.rootBeanDefinition(Test2Service.class).getBeanDefinition();
registry.registerBeanDefinition(“test2Service”, myBean);

其他相关的类代码:

  • Service1.java
package com.niewj.util;

import org.springframework.stereotype.Component;

@Component
public class Service1 {

    public Service2 getService2() {
        return service2;
    }

    public void setService2(Service2 service2) {
        this.service2 = service2;
    }

    private Service2 service2;

    public void doBusiness(){
        System.out.println("Service1.doBusiness");
        service2.doSth();
    }

}
  • Service2.java
package com.niewj.util;

public class Service2 {

    public void doSth(){
        System.out.println("Service2.doSth: 执行了!");
    }
}
  • Pojo4.java
package com.niewj.bean;

public class Pojo4 {
    public Pojo4(){
        System.out.println("Pojo4[无注解java类] 初始化~~~");
    }
}
  • User.java
package com.niewj.bean;

import lombok.Data;

@Data
public class User {
    private String name;
    private String passwd;
    private boolean online ;

    public User(String name, String passwd, boolean online){
        System.out.println("User-初始化!");
        this.name = name;
        this.passwd = passwd;
        this.online = online;
    }

    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                ", passwd='" + passwd + '\'' +
                ", online=" + online +
                '}';
    }
}
  • 配置类: TestBeanCreationConfig.java
package com.niewj.config;

import com.niewj.bean.User;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

@Configuration
@ComponentScan(basePackages = "com.niewj.util")
public class TestBeanCreationConfig {

    @Bean
    public User user() {
        return new User("u", "122", false);
    }
}
  • 测试用例: BeanCreationTest.java
package com.niewj;

import com.niewj.config.TestBeanCreationConfig;
import com.niewj.util.Service1;
import com.niewj.util.Service2;
import org.junit.Test;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

import java.util.stream.Stream;

/**
 * spring bean创建和初始化测试:
 *  BeanFactoryPostProcessor
 *  BeamDefinitionRegistryPostProcessor
 */
public class BeanCreationTest {

    @Test
    public void testBeanCreation() {
        AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
        ctx.register(TestBeanCreationConfig.class);
        ctx.refresh();

        // 打印spring容器中的 BeanDefinition
        Stream.of(ctx.getBeanDefinitionNames()).forEach(e -> System.out.println(e));
        System.out.println("============Service1#doBusiness()=================");

        Service1 service1 = ctx.getBean(Service1.class);
        service1.doBusiness();
        System.out.println("======Service2#doSth()=====");
        Service2 service2 = ctx.getBean(Service2.class);
        service2.doSth();

        ctx.close();
    }
}
  • output: 控制台输出:
===> MyBeanDefinitionRegistryPostProcessor#postProcessBeanDefinitionRegistry 调用!!!
registry instanceof BeanFactory: true
###->MyBeanDefinitionRegistryPostProcessor注册bean:[Service2.class]###-> begin
###->MyBeanDefinitionRegistryPostProcessor注册bean:[Service2.class]###-> over
###->MyBeanDefinitionRegistryPostProcessor注册bean:[Pojo4.class]###-> begin
###->MyBeanDefinitionRegistryPostProcessor注册bean:[Pojo4.class]###-> over
===> MyBeanDefinitionRegistryPostProcessor#postProcessBeanFactory-->可以获取容器内bean定义的数量->getBeanDefinitionCount=> 13
===> MyBeanDefinitionRegistryPostProcessor#postProcessBeanFactory-->可以打印容器中的所有 定义的BeanDefinition->getBeanDefinitionNames:    
[org.springframework.context.annotation.internalConfigurationAnnotationProcessor, org.springframework.context.annotation.internalAutowiredAnnotationProcessor, org.springframework.context.annotation.internalCommonAnnotationProcessor, org.springframework.context.event.internalEventListenerProcessor, org.springframework.context.event.internalEventListenerFactory, testBeanCreationConfig, myBeanDefinitionRegistryPostProcessor, myBeanFactoryPostProcessor, myBeanPostProcessor, service1, user, service2, myPojo4]
===> MyBeanFactoryPostProcessor#postProcessBeanFactory-->可以获取容器内bean定义的数量->getBeanDefinitionCount=> 13
===> MyBeanFactoryPostProcessor#postProcessBeanFactory-->可以打印容器中的所有 定义的BeanDefinition->getBeanDefinitionNames:
[org.springframework.context.annotation.internalConfigurationAnnotationProcessor, org.springframework.context.annotation.internalAutowiredAnnotationProcessor, org.springframework.context.annotation.internalCommonAnnotationProcessor, org.springframework.context.event.internalEventListenerProcessor, org.springframework.context.event.internalEventListenerFactory, testBeanCreationConfig, myBeanDefinitionRegistryPostProcessor, myBeanFactoryPostProcessor, myBeanPostProcessor, service1, user, service2, myPojo4]
MyBeanPostProcessor-初始化!
###->MyBeanPostProcessor#postProcessBeforeInitialization->beanName=[testBeanCreationConfig]###-> begin
###->MyBeanPostProcessor#postProcessBeforeInitialization->beanName=[testBeanCreationConfig]###-> end
###->MyBeanPostProcessor#postProcessAfterInitialization->beanName=[testBeanCreationConfig]###-> begin
###->MyBeanPostProcessor#postProcessAfterInitialization->beanName=[testBeanCreationConfig]###-> end
###->MyBeanPostProcessor#postProcessBeforeInitialization->beanName=[service1]###-> begin
bean=com.niewj.util.Service1@77167fb7; bean依赖为: null
###->MyBeanPostProcessor#postProcessBeforeInitialization->beanName=[service1]###-> end
###->MyBeanPostProcessor#postProcessAfterInitialization->beanName=[service1]###-> begin
bean=com.niewj.util.Service1@77167fb7; bean依赖为: com.niewj.util.Service2@1fe20588
###->MyBeanPostProcessor#postProcessAfterInitialization->beanName=[service1]###-> end
User-初始化!
###->MyBeanPostProcessor#postProcessBeforeInitialization->beanName=[user]###-> begin
###->MyBeanPostProcessor#postProcessBeforeInitialization->beanName=[user]###-> end
###->MyBeanPostProcessor#postProcessAfterInitialization->beanName=[user]###-> begin
###->MyBeanPostProcessor#postProcessAfterInitialization->beanName=[user]###-> end
###->MyBeanPostProcessor#postProcessBeforeInitialization->beanName=[service2]###-> begin
###->MyBeanPostProcessor#postProcessBeforeInitialization->beanName=[service2]###-> end
###->MyBeanPostProcessor#postProcessAfterInitialization->beanName=[service2]###-> begin
###->MyBeanPostProcessor#postProcessAfterInitialization->beanName=[service2]###-> end
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
testBeanCreationConfig
myBeanDefinitionRegistryPostProcessor
myBeanFactoryPostProcessor
myBeanPostProcessor
service1
user
service2
myPojo4
============Service1#doBusiness()=================
Service1.doBusiness
Service2.doSth: 执行了!
======Service2#doSth()=====
Service2.doSth: 执行了!

4. 执行顺序解析

  1. BeanDefinitionRegistryPostProcessor#postProcessBeanDefinitionRegistry 可以拿到 BeanDefinitionRegistry, 可用来注册bean; 这里注册了2个bean这里 Service2.classPojo4.class 1-6行

  2. BeanDefinitionRegistryPostProcessor#postProcessBeanFactory 可以拿到 BeanFactory ; 这里打印里已有的bean定义数量 和 BeanFactory里所有的bean定义内容; 7-9行

  3. BeanFactoryPostProcessor#postProcessBeanFactory 可以拿到 BeanFactory; 这里同样打印了bean定义数量和BeanFactory里所有的bean定义内容; 10-12行

    – 上面两个PostProcessor是BeanFactory相关的, 只会执行一次; 下面的 BPP(BeanPostProcessor)则不同, BPP是每个Bean都要过一遍; 可以用来对Bean进行过滤做一些拦截处理:

  4. 遍历: BeanPostProcessor#postProcessBeforeInitialization 这里输出了每个bean的 beanName; 并过滤了一个bean:Service1, 如果是它, 就给手动注入了一个Service2对象; 12-32行

  5. 遍历: BeanPostProcessor#postProcessAfterInitialization 这里输出了每个bean的 beanName; 并过滤了一个bean:Service1, 获取到它的Service2对象, 可以看到非null了; 12-32行

  6. 上面流程就是3个PostProcessor的顺序关系; 后面的 33-45行就是 Stream.of(ctx.getBeanDefinitionNames()).forEach(e -> System.out.println(e));打印的内容了;

5. 小结

3个PostProcessor的执行顺序:

(1). BeanDefinitionRegistryPostProcessor# postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) ;

(2). BeanFactoryPostProcessor#postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory);

(3). BeanPostProcessor# postProcessBeforeInitialization(Object bean, String beanName)

(4). BeanPostProcessor# postProcessAfterInitialization(Object bean, String beanName)


转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 hi@niewj.com

×

喜欢就点赞,疼爱就打赏