扩展(一):自定义BFPP
上一篇讲invokeBeanFactoryPostProcessor()方法逻辑时说到了beanFactoryPostProcessors参数,会在方法调用时优先进行处理,并且里面都是继承了BeanDefinitionRegistryPostProcessor的自定义扩展类。
本篇会介绍如何扩展自定义的BeanDefinitionRegistryPostProcessor类。
invokeBeanFactoryPostProcessors
protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
if (beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
}
}
先来看看getBeanFactoryPostProcessors()方法。
public abstract class AbstractApplicationContext extends DefaultResourceLoader implements ConfigurableApplicationContext {
//方法直接return类中beanFactoryPostProcessors属性值
public List<BeanFactoryPostProcessor> getBeanFactoryPostProcessors() {
return this.beanFactoryPostProcessors;
}
//有get就会有add(set)
@Override
public void addBeanFactoryPostProcessor(BeanFactoryPostProcessor postProcessor) {
this.beanFactoryPostProcessors.add(postProcessor);
}
那么我们只要自定义类,继承AbstractApplicationContext 类并实现addBeanFactoryPostProcessor()方法将我们自定义的类加进去即可。
自定义ApplicationContext
自定义ApplicationContext继承ClassPathXmlApplicationContext ,并重写customizeBeanFactory方法,显式调用addBeanFactoryPostProcessor(),将我们自定义的MyCustomBFPP添加进去。
public class MyCustomApplicationContext extends ClassPathXmlApplicationContext {
public MyCustomApplicationContext(String... configLocations) throws BeansException {
super(configLocations);
}
@Override
protected void customizeBeanFactory(DefaultListableBeanFactory beanFactory) {
super.addBeanFactoryPostProcessor(new MyCustomBFPP());
}
}
类关系图
自定义BFPP
自定义的MyCustomBFPP 实现了BeanFactoryPostProcessor 类,
public class MyCustomBFPP implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
System.out.println("MyCustomBDRPP.postProcessBeanFactory");
}
main
使用我们自定义的ApplicationContext加载xml文件,那么在执行customizeBeanFactory方法时,就会将我们自定义的MyCustomBFPP加进去,此时在invokeBeanFactoryPostProcessors()方法的beanFactoryPostProcessors参数中,就会看到我们的扩展类
public class Test {
public static void main(String[] args) {
MyCustomApplicationContext ac = new MyCustomApplicationContext("applicationContext.xml");
}
}
扩展(二):getBeanNamesForType
上一篇介绍invokeBeanFactoryPostProcessors()方法整体执行流程时,方法内多次调用getBeanNamesForType()方法,每次都重新获取所有BeanDefinitionRegistryPostProcessor接口的bean的beanName。
目的是为了防止在上一步执行postProcessBeanDefinitionRegistry方法后,产生新的BDRPP类 。
举个栗子:自定义一个类,这个类有如下要求
- 继承BeanDefinitionRegistryPostProcessor重写postProcessBeanDefinitionRegistry()方法
- 在postProcessBeanDefinitionRegistry()方法中,生成新的、同样继承了BeanDefinitionRegistryPostProcessor的类。
- 自定义的类可以让Spring识别管理。
在xml中通过bean标签的形式,可以让Spring加载xml时进行解析封装成Definition并注册到BeanFacroty。
xml中声明
<bean class="com.xxx.bdrpp.CustomBDRPP"></bean>
自定义BDRPP
自定义BDRPP,实现BeanDefinitionRegistryPostProcessor重写postProcessBeanDefinitionRegistry()时,声明了RootBeanDefinition并在构造方法中传入要生成的CustomRegistryBDRPP.class。
同时实现PriorityOrdered 类是为了在源码中可以优先执行。
public class CustomBDRPP implements BeanDefinitionRegistryPostProcessor, PriorityOrdered {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
System.out.println("CustomBDRPP.postProcessBeanFactory");
}
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
//写法1
//BeanDefinitionBuilder bdb = BeanDefinitionBuilder.rootBeanDefinition(CustomRegistryBDRPP.class);
//registry.registerBeanDefinition("myCustom",bdb.getBeanDefinition());
//写法2
registry.registerBeanDefinition("myCustom",new RootBeanDefinition(CustomRegistryBDRPP.class));
// 无论写法1还是写法2, 都是相当于将CustomRegistryBDRPP封装进Definition,并注册到BeanFactory的beanDefinitionMap和beanDefinitionNames中
System.out.println("CustomBDRPP.postProcessBeanDefinitionRegistry");
}
@Override
public int getOrder() {
return 0;
}
}
要在postProcessBeanDefinitionRegistry方法中新加入的CustomRegistryBDRPP。
public class CustomRegistryBDRPP implements BeanDefinitionRegistryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
System.out.println("CustomRegistryBDRPP----postProcessBeanFactory");
}
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
System.out.println("CustomRegistryBDRPP----postProcessBeanDefinitionRegistry");
}
}
接下来,我们来看一下执行流程,Spring是如何解析的CustomBDRPP 以及在执行postProcessBeanDefinitionRegistry方法时是如何识别到CustomRegistryBDRPP的。
执行流程
源码片段
public static void invokeBeanFactoryPostProcessors(
ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {
// 用于保存本次要执行的BeanDefinitionRegistryPostProcessor
List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();
// 调用所有实现PriorityOrdered接口的BeanDefinitionRegistryPostProcessor实现类
// 找到所有实现BeanDefinitionRegistryPostProcessor接口bean的beanName
String[] postProcessorNames =
beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
// 遍历处理所有符合规则的postProcessorNames
for (String ppName : postProcessorNames) {
// 检测是否实现了PriorityOrdered接口
if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
// 获取名字对应的bean实例,添加到currentRegistryProcessors中
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
// 将要被执行的BFPP名称添加到processedBeans,避免后续重复执行
processedBeans.add(ppName);
}
}
// 按照优先级进行排序操作
sortPostProcessors(currentRegistryProcessors, beanFactory);
// 添加到registryProcessors中,用于最后执行postProcessBeanFactory方法
registryProcessors.addAll(currentRegistryProcessors);
// 遍历currentRegistryProcessors,执行postProcessBeanDefinitionRegistry方法
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
// 执行完毕之后,清空currentRegistryProcessors
currentRegistryProcessors.clear();
//再次获取实现BeanDefinitionRegistryPostProcessor的BeanName
postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
}
而当CustomBDRPP类执行完invokeBeanDefinitionRegistryPostProcessors()方法时,方法的底层逻辑会将自定义的CustomRegistryBDRPP封装进Definition,并注册到BeanFactory的beanDefinitionMap和beanDefinitionNames中
此时再次调用getBeanNamesForType(),就可以获取到我们通过invokeBeanDefinitionRegistryPostProcessors方法创建的CustomRegistryBDRPP。