BeanFactory扩展
Spring 中有 2 个非常重要的接口:BeanFactoryPostProcessor 和 BeanDefinitionRegistryPostProcessor,这 2 个接口。
Spring 容器中主要的 4 个阶段
阶段 1:Bean 注册阶段,此阶段会完成所有 bean 的注册。
阶段 2:BeanFactory 后置处理阶段。
阶段 3:注册 BeanPostProcessor
阶段 4:Bean 插件阶段,此阶段完成所有单例 Bean 的注册和装载操作。
阶段1:Bean 注册阶段
概述
spring 中所有 bean 的注册都会在此阶段完成,按照规范,所有 bean 的注册必须在此阶段进行,其他阶段不要再进行 bean 的注册。
这个阶段 spring 为我们提供 1 个接口:BeanDefinitionRegistryPostProcessor,spring 容器在这个阶段中会获取容器中所有类型为 BeanDefinitionRegistryPostProcessor
的 bean,然后会调用他们的postProcessBeanDefinitionRegistry
方法,源码如下,方法参数类型是 BeanDefinitionRegistry
,这个类型大家都比较熟悉,即 bean 定义注册器,内部提供了一些方法可
以用来向容器中注册 bean。
public interface BeanDefinitionRegistryPostProcessor extends
BeanFactoryPostProcessor {
void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry)
throws BeansException;
}
这个接口还继承了 BeanFactoryPostProcessor
接口。
当容器中有多个 BeanDefinitionRegistryPostProcessor
的时候,可以通过下面任意一种方式来指定顺序。
实现
org.springframework.core.PriorityOrdered
接口实现
org.springframework.core.Ordered
接口
执行顺序
PriorityOrdered.getOrder() asc,Ordered.getOrder() asc
BeanDefinitionRegistryPostProcessor 简单使用
@Component
public class MyBeanDefinitionRegistryPostProcessor
implements BeanDefinitionRegistryPostProcessor {
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry)
throws BeansException {
AbstractBeanDefinition userNameBdf = BeanDefinitionBuilder.genericBeanDefinition(String.class)
.addConstructorArgValue("xiaou")
.getBeanDefinition();
registry.registerBeanDefinition("username", userNameBdf);
}
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)
throws BeansException {
}
}
@ComponentScan
public class MyMainConfigure {}
java 测试方法
@Test
public void test1() {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
context.register(MyMainConfigure.class);
context.refresh();
System.out.println(context.getBean("username"));
}
输出
xiaou
多个指定顺序
下面我们定义 2 个 BeanDefinitionRegistryPostProcessor
,都实现 Ordered 接口,第一个 order 的 值为 2,第二个 order 的值为 1,我们来看一下具体执行的顺序。
@Component
public class MyBeanDefinitionRegistryPostProcessor
implements BeanDefinitionRegistryPostProcessor, Ordered {
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry)
throws BeansException {
AbstractBeanDefinition userNameBdf = BeanDefinitionBuilder.genericBeanDefinition(String.class)
.addConstructorArgValue("xiaou")
.getBeanDefinition();
registry.registerBeanDefinition("username", userNameBdf);
}
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)
throws BeansException {
}
@Override
public int getOrder() {
return 2;
}
}
@Component
public class MyBeanDefinitionRegistryPostProcessor2
implements BeanDefinitionRegistryPostProcessor, Ordered {
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry)
throws BeansException {
AbstractBeanDefinition userNameBdf = BeanDefinitionBuilder.genericBeanDefinition(String.class)
.addConstructorArgValue("把卡把卡")
.getBeanDefinition();
registry.registerBeanDefinition("petName", userNameBdf);
}
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)
throws BeansException {
}
@Override
public int getOrder() {
return 0;
}
}
测试方法
@Test
public void test2() {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
context.register(MyMainConfigure.class);
context.refresh();
context.getBeansOfType(String.class).forEach((beanName, bean) ->
System.out.println(String.format("%s->%s", beanName, bean)));
}
输出
petName->把卡把卡
username->xiaou
BeanFactory 后置处理阶段
描述
在这个阶段 Spring 容器已经完成所有 bean 的注册,这个阶段中可以对 BeanFactory 中的一下信息进行修改,比如改阶段 1 中一些 bean 的定义信息,修改 BeanFactory 的一些配置等等,此阶段 spring 也提供了一个接口来进行扩展: BeanFactoryPostProcessor ,简称 bfpp ,接口中有个方法 postProcessBeanFactory
,spring 会获取容器中所有 BeanFactoryPostProcessor 类型的 bean,然后调用他们的 postProcessBeanFactory
,来看一下这个接口的源码:
@FunctionalInterface
public interface BeanFactoryPostProcessor {
void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)
throws BeansException;
}
当容器中有多个 BeanFactoryPostProcessor
的时候,可以通过下面任意一种方式来指定顺序
实现
org.springframework.core.PriorityOrdered
接口实现
org.springframework.core.Ordered
接口
执行顺序
PriorityOrdered.getOrder() asc,Ordered.getOrder() asc
实验
在 BeanFactoryPostProcessor 来修改 bean 中已经注册的 bean 定义的信息,给一个 bean 属性设置一个值。
@Component
public class MyBeanFactoryPostProcessor
implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)
throws BeansException {
System.out.println("准备修改类信息");
BeanDefinition user1 = beanFactory.getBeanDefinition("user1");
user1.getPropertyValues().add("name", "xiaoY");
}
}
user1 Bean
@Bean
public Users user1() {
System.out.println("user1 被执行了");
return new Users()
.setAge(18)
.setName("xiaou");
}
测试方法
@Test
public void test3() {
AnnotationConfigApplicationContext context =
new AnnotationConfigApplicationContext();
context.register(MyMainConfigure.class);
context.refresh();
System.out.println(context.getBean("user1"));
}
输出
准备修改类信息
Users(name=xiaoY, age=18, father=null)