Spring的BeanDefinitionRegistryPostProcessor接口详解
BeanDefinitionRegistryPostProcessor介绍
BeanDefinitionRegistryPostProcessor 它是Spring框架的一个扩展点,用于对Bean定义的注册过程进行干预和定制,例如添加,修改或删除Bean定义等。
BeanDefinitionRegistryPostProcessor 它继承BeanFactoryPostProcessor接口,并在其基础上扩展了一个新的方法,即:postProcessBeanDefinitionRegistry()方法。
BeanFactoryPostProcessor源码:
@FunctionalInterface
public interface BeanFactoryPostProcessor {
void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;
}
BeanDefinitionRegistryPostProcessor源码:
public interface BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor {
void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException;
}
Spring容器初始化时,从资源中读取到bean的相关定义后,保存在beanDefinitionMap,实例化bean的操作就是依据这些bean的定义来做的,而在实例化之前,Spring允许我们通过自定义扩展来改变bean的定义,定义一旦变了,后面的实例也就变了,而beanFactory后置处理器,即BeanFactoryPostProcessor就是用来改变bean定义的。
BeanDefinitionRegistryPostProcessor继承了BeanFactoryPostProcessor接口,BeanFactoryPostProcessor的实现类在其postProcessBeanFactory方法被调用时,可以对bean的定义进行控制,因此BeanDefinitionRegistryPostProcessor的实现类一共要实现以下两个方法:
- void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException:该方法的实现中,主要用来对bean定义做一些改变。
- void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException:该方法用来注册更多的bean到spring容器中,详细观察入参BeanDefinitionRegistry接口,看看这个参数能带给我们什么能力。
从BeanDefinitionRegistry可以看到,BeanDefinitionRegistry提供了丰富的方法来操作BeanDefinition,判断、注册、移除等方法都准备好了,我们在编写postProcessBeanDefinitionRegistry方法的内容时,就能直接使用入参registry的这些方法来完成判断和注册、移除等操作。
BeanFactoryPostProcessor和BeanDefinitionRegistryPostProcessor的区别
BeanFactoryPostProcessor可以修改各个注册的Bean,BeanDefinitionRegistryPostProcessor可以动态将Bean注册。
BeanDefinitionRegistryPostProcessor的执行时机
postProcessBeanDefinitionRegistry执行时机
- AbstractApplicationContext#refresh
- PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors
优先执行实现了PriorityOrdered接口的BeanDefinitionRegistryPostProcessor,其次就是实现了接口Ordered的,最后才是两者都没有的。
调用BeanDefinitionRegistryPostProcessor的postProcessBeanDefinitionRegistry方法。
postProcessBeanFactory执行时机
跟BeanDefinitionRegistryPostProcessor的调用路径一样,在调用了所有的BeanDefinitionRegistryPostProcessor的postProcessBeanDefinitionRegistry方法后,紧接着就会处理所有的BeanFactoryPostProcessor,按优先级调用其postProcessBeanFactory接口。
源码-来自:PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors
优先执行实现了PriorityOrdered接口的BeanFactoryPostProcessor,其次就是实现了接口Ordered的,最后才是两者都没有的。
重要实现类
ConfigurationClassPostProcessor
Spring中的BeanDefinitionRegistryPostProcessor的实现类ConfigurationClassPostProcessor,通过这个类会将Spring中@Configuration、@Import、@Bean等注解的类扫描出来,并封装成BeanDefinition注册进容器中。
后置处理器ConfigurationClassPostProcessor如何解析注解
自定义实现方式
- 在postProcessBeanDefinitionRegistry()方法被调用的时候手工在Spring中注册了Student类的BeanDefinition信息;
- 在postProcessBeanFactory()方法被调用的时候,从Spring容器中取出Dog类的BeanDefinition信息和Student类的实例;
@Data
public class Student{
private String name;
private String age;
}
@Component
public class MyBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
//手工定义一个beanDefinition实例
RootBeanDefinition beanDefinition = new RootBeanDefinition();
//给beanDefinition填充属性
beanDefinition.setBeanClass(Student.class);
MutablePropertyValues propertyValues = new MutablePropertyValues();
PropertyValue propertyValue1 = new PropertyValue("name", "张三");
PropertyValue propertyValue2 = new PropertyValue("age", "11");
propertyValues.addPropertyValue(propertyValue1);
propertyValues.addPropertyValue(propertyValue2);
beanDefinition.setPropertyValues(propertyValues);
//注册手工定义的beanDefinition
registry.registerBeanDefinition("student", beanDefinition);
}
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
System.out.println("-----------postProcessBeanFactory start------------");
//根据类名取出手工注册的beanDefinition
BeanDefinition beanDefinition = beanFactory.getBeanDefinition("student");
System.out.println(beanDefinition.getBeanClassName());
//根据类从容器中取出手工注册的beanDefinition所描述的实例bean
Student student = beanFactory.getBean(Student.class);
System.out.println(student.getName());
System.out.println(student.getAge());
System.out.println("-----------postProcessBeanFactory end------------");
}