图片
1、扩展定义一个Dog类,扩展name属性默认为“旺财”,扩展颜色默认为“黑色”;
复制@Data @Component public class Dog { private String name="旺财"; private String color="黑色"; }1.2.3.4.5.6.2、扩展定义一个实现类(MyBeanFactoryPostProcessor),扩展实现BeanFactoryPostProcessor接口,扩展重写postProcessBeanFactory()方法,扩展并Dog类的扩展属性name修改为“狗蛋”;并用@Component注解标记BeanFactoryPostProcessor接口的实现类(MyBeanFactoryPostProcessor)
复制@Component @Slf4j public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor { @Override public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { log.info("com.fanfu.config.MyBeanFactoryPostProcessor.postProcessBeanFactory被执行"); ScannedGenericBeanDefinition dog = ((ScannedGenericBeanDefinition) beanFactory.getBeanDefinition("dog")) ; MutablePropertyValues propertyValues = dog.getPropertyValues(); propertyValues.addPropertyValue("name", "狗蛋儿"); log.info("修改Dog的BeanDefinition对象中的name属性为狗蛋儿"); } }1.2.3.4.5.6.7.8.9.10.11.12.3、编写单元测试验证结果
复制@SpringBootTest @Slf4j public class FanfuApplicationTests { @Test public void test(){ AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext("com.fanfu"); Dog dog = ((Dog) context.getBean("dog")); log.info(dog.getName()); Assert.isTrue(dog.getName().equals("狗蛋儿"),扩展 "属性修改失败"); } }1.2.3.4.5.6.7.8.9.10.11.4、验证结果表明,扩展自定义的BeanFactoryPostProcessor接口的实现类(MyBeanFactoryPostProcessor),可以在容器读取到Bean的BeanDefinition数据之后,bean未实例化前,读取BeanDefiniion数据,并且根据需要进行修改,那么自定义的BeanFactoryPostProcessor接口的云服务器实现类(MyBeanFactoryPostProcessor)的工作原理是什么呢?BeanFactoryPostProcessor接口的实现类是什么时候实例化的?MyBeanFactoryPostProcessor#postProcessBeanFactory方法是如何被调用的?接着往下看。
BeanFactoryPostProcessor接口的实现类是什么时候实例化的?
1、BeanFactoryPostProcessor接口的实现类(MyBeanFactoryPostProcessor)被@Component标记,在窗口启动的时候会被封装成BeanDefinition对象注册到容器中;
图片
2、PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors()方法被执行时,会按照类型从Spring容器中找到所有BeanFactoryPostProcessor类型的实现类的名称;
图片
3、在上一步中得到所有BeanFactoryPostProcessor类型的实现类的名称的名称后,再循环一次,来对BeanFactoryPostProcessor的实现类进行实例化 (beanFacotry.getBean()去获取MyBeanFactoryPostProcessor的实例,如果获取不到,就创建一个);
图片
MyBeanFactoryPostProcessor#postProcessBeanFactory方法是如何被调用的?
1、在单元测试中构建了一个AnnotationConfigApplicationContext对象,亿华云AnnotationConfigApplicationContext的构造方法如下:
public AnnotationConfigApplicationContext(String... basePackages) { this(); scan(basePackages); refresh(); }
2、从上面的AnnotationConfigApplicationContext的构造方法中,可以看到又调用了refresh(),这里实际最终被调用的是AbstractApplicationContext#refresh(),这个方法也是Spring容器启动的关键方法,在分析Spring相关的源码时会经常碰到。
3、AbstractApplicationContext#refresh()中,调用AbstractApplicationContext#invokeBeanFactoryPostProcessors方法才正式开始了BeanFactoryPostProcessor接口的所有实现类的postProcessBeanFactory()方法调用;
4、跟着AbstractApplicationContext#invokeBeanFactoryPostProcessors方法进去,会发现这里只是一个入口,实际承担调用执行任务的是PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors()方法;
5、跟着PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors()方法进去后,会发现里面真的是别有洞天,很容易迷路(牢牢带着自己的问题分析源码找答案,不要被除自己问题以外的东西迷了眼,云南idc服务商一定会柳暗花明),另外org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor的实现类的调用也在这个方法,所以这个方法的含金量很高,那就单独拎出来仔细分析一下,建议debug一步一步看,多看几遍就能明白,其实也很简单,唯一的难点就是这个方法有点长,需要多点耐心和时间。
复制public static void invokeBeanFactoryPostProcessors( ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) { //之所以说这个方法的含金量很高, //是因为在这个方法里是先执行BeanDefinitionRegistryPostProcessor实现类的postProcessBeanDefinitionRegistry方法;//然后才接着执行BeanFactoryPostProcessor接口的实现类的postProcessBeanFactory方法 //这两个接口很表面上看很类似,实际在执行的时机和功能上是有明显区别的 Set<String> processedBeans = new HashSet<>(); //AnnotationConfigApplicationContext继承于GenericApplicationContext, //而GenericApplicationContext又实现了BeanDefinitionRegistry接口 //所以这里会进入if语句中 if (beanFactory instanceof BeanDefinitionRegistry) { BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory; List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>(); List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>(); //这里提前执行的BeanFactoryPostProcessor,是在准备上下文环境时,发布了ApplicationPreparedEvent事件;//触发监听器,通过AbstractApplicationContext#addBeanFactoryPostProcessor注册进来的;//这里并不是这次要重点分析的内容,可以先跳过这;for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) { if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) { BeanDefinitionRegistryPostProcessor registryProcessor = (BeanDefinitionRegistryPostProcessor) postProcessor; registryProcessor.postProcessBeanDefinitionRegistry(registry); registryProcessors.add(registryProcessor); } else { regularPostProcessors.add(postProcessor); } } List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>(); // 从32行到72行,是在执行BeanDefinitionRegistryPostProcessor实现类的postProcessBeanDefinitionRegistry方法;//执行的过程也是有点小区折的,分三步,第一,执行实现了PriorityOrdered接口的实现类. String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false); for (String ppName : postProcessorNames) { if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) { currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class)); processedBeans.add(ppName); } } sortPostProcessors(currentRegistryProcessors, beanFactory); registryProcessors.addAll(currentRegistryProcessors); invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry); currentRegistryProcessors.clear(); // 第二,执行实现了Ordered接口的实现类;postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false); for (String ppName : postProcessorNames) { if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) { currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class)); processedBeans.add(ppName); } } sortPostProcessors(currentRegistryProcessors, beanFactory); registryProcessors.addAll(currentRegistryProcessors); invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry); currentRegistryProcessors.clear(); //第三,执行剩下其他的BeanDefinitionRegistryPostProcessor实现类;boolean reiterate = true; while (reiterate) { reiterate = false; postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false); for (String ppName : postProcessorNames) { if (!processedBeans.contains(ppName)) { currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class)); processedBeans.add(ppName); reiterate = true; } } sortPostProcessors(currentRegistryProcessors, beanFactory); registryProcessors.addAll(currentRegistryProcessors); invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry); currentRegistryProcessors.clear(); } // BeanDefinitionRegistryPostProcessor继承了BeanFactoryPostProcessor, //所以这部分实现类的postProcessBeanFactory()会提前执行 invokeBeanFactoryPostProcessors(registryProcessors, beanFactory); //第26行,非BeanDefinitionRegistryPostProcessor类型的BeanFactoryPostProcessor实现类会在这执行 invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory); } else { invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory); } //BeanDefinitionRegistryPostProcessor接口的实现类上面已执行执行完了 //下面开始准备执行BeanFactoryPostProcessor接口的实现类 String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false); // 正式执行前,把BeanFactoryPostProcessor接口的实现类分成了三类, //分别是实现了PriorityOrdered接口,实现了Ordered接口,其他; List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<>(); List<String> orderedPostProcessorNames = new ArrayList<>(); List<String> nonOrderedPostProcessorNames = new ArrayList<>(); for (String ppName : postProcessorNames) { if (processedBeans.contains(ppName)) { // skip - already processed in first phase above } else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) { priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class)); } else if (beanFactory.isTypeMatch(ppName, Ordered.class)) { orderedPostProcessorNames.add(ppName); } else { nonOrderedPostProcessorNames.add(ppName); } } // 分好类,第一,先执行实现了PriorityOrdered接口的实现类;sortPostProcessors(priorityOrderedPostProcessors, beanFactory); invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory); // 第二,执行实现了Ordered接口的实现类;List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size()); for (String postProcessorName : orderedPostProcessorNames) { orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class)); } sortPostProcessors(orderedPostProcessors, beanFactory); invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory); //第三,执行未实现上面两个接口的实现类,自定义的MyBeanFactoryPostProcessor就是在这里被执行的 //其实,也很简单的,和BeanDefinitionRegistryPostProcessor接口的实现类的执行过程类似;List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size()); for (String postProcessorName : nonOrderedPostProcessorNames) { nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class)); } invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory); beanFactory.clearMetadataCache(); }1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17.18.19.20.21.22.23.24.25.26.27.28.29.30.31.32.33.34.35.36.37.38.39.40.41.42.43.44.45.46.47.48.49.50.51.52.53.54.55.56.57.58.59.60.61.62.63.64.65.66.67.68.69.70.71.72.73.74.75.76.77.78.79.80.81.82.83.84.85.86.87.88.89.90.91.92.93.94.95.96.97.98.99.100.101.102.103.104.105.106.107.108.109.110.111.112.这里我画了一个时序图,可以更直观的看到整个调用过程,也可以照着这个图,一步一步debug来了解整个过程;
图片
通过分析PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors()方法,postProcessBeanFactory()与postProcessBeanDefinitionRegistry()的区别已经很明显了,这里再总结一下(总结的有不准的地方,还请小伙伴在评论区告诉我,一块进步):
BeanDefinitionRegistryPostProcessor接口的实现类的postProcessBeanDefinitionRegistry方法要优先于BeanFactoryPostProcessor接口的实现类的postProcessBeanFactory方法执行;postProcessBeanDefinitionRegistry方法形参是BeanDefinitionRegistry,postProcessBeanFactory方法的形参是ConfigurableListableBeanFactory,在功能上会有一些区别;需要注意的是DefaultListableBeanFactory实现了BeanDefinitionRegistry和ConfigurableListableBeanFactory接口;BeanDefinitionRegistryPostProcessor继承了BeanFactoryPostProcessor,关于BeanDefinitionRegistryPostProcessor可以移步这里:Springboot扩展点之BeanDefinitionRegistryPostProcessor;对敏感信息的解密处理,比如数据库连接信息加密和解密:在实际的业务开发中,在配置文件中明文配置mysq,redis的密码实际上是不安全的,需要配置加密后的密码信息;但是把加密后的密码信息注入的数据源中,去连接mysql数据库肯定会连接异常,因为mysql并不知道你的加密方式和加密方法。这就会产生一个需求:需要在配置文件中配置的数据库信息是加密的,但是在把密码信息注入数据源前在程序里解密处理。
BeanFactoryPostProcessor正好可以解决这个问题,在真正使用到数据源去连接数据库前,读取到加密信息,进行解密处理,再用解密后的信息替换掉Spring容器中加密信息。