大致整理下面这些类的作用和关系:
BeanPostProcessor
Bean初始化的后置处理器;BeanFactoryPostProcessor
BeanFactory的后置处理器;BeanDefinitionRegistryPostProcessor
是BeanFactoryPostProcessor
的子接口, 新增了一个方法!
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. 执行顺序解析
BeanDefinitionRegistryPostProcessor#postProcessBeanDefinitionRegistry
可以拿到 BeanDefinitionRegistry, 可用来注册bean; 这里注册了2个bean这里Service2.class
和Pojo4.class
1-6行BeanDefinitionRegistryPostProcessor#postProcessBeanFactory
可以拿到 BeanFactory ; 这里打印里已有的bean定义数量 和 BeanFactory里所有的bean定义内容; 7-9行BeanFactoryPostProcessor#postProcessBeanFactory
可以拿到 BeanFactory; 这里同样打印了bean定义数量和BeanFactory里所有的bean定义内容; 10-12行– 上面两个PostProcessor是BeanFactory相关的, 只会执行一次; 下面的 BPP(BeanPostProcessor)则不同, BPP是每个Bean都要过一遍; 可以用来对Bean进行过滤做一些拦截处理:
遍历:
BeanPostProcessor#postProcessBeforeInitialization
这里输出了每个bean的 beanName; 并过滤了一个bean:Service1, 如果是它, 就给手动注入了一个Service2对象; 12-32行遍历:
BeanPostProcessor#postProcessAfterInitialization
这里输出了每个bean的 beanName; 并过滤了一个bean:Service1, 获取到它的Service2对象, 可以看到非null了; 12-32行上面流程就是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