写点什么

Spring 源码学习 11:invokeBeanFactoryPostProcessors

发布于: 2020 年 12 月 28 日

前言


invokeBeanFactoryPostProcessors 会执行 BeanFactory 的后置处理器。看到这里会有疑问:


  1. 什么是 BeanFactoryPostProcessor ?

  2. BeanfactoryPostProcessor 该如何使用?


知道了上面两个问题的答案,对 BeanFactoryPostProcessor 有了了解之后,然后再深入源码,继续阅读 invokeBeanFactoryPostProcessors 这个方法。


作用


资料还是在官网可以找到答案:



阅读了一下,大概意思是 Spring IoC 容器允许 BeanFactoryPostProcessor 读取配置元数据,并有可能在容器实例化除 BeanFactoryPostProcessor 实例以外的任何 bean 之前更改它。


同样可以使用 Ordered 接口对 BeanFactoryPostProcessor 进行排序。


注意



BeanFactoryPostProcessor 操作的是 BeanDefinition ,即元数据。但是同样可以通过获取到 BeanFactory 进行实例化 Bean,但是官网很不建议这样使用。


示例


使用 BeanFactoryPostProcessor


@Componentpublic class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
@Override public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
// 修改 BeanDefinition 信息 BeanDefinition userComponentBeanDefinition = beanFactory.getBeanDefinition("userComponent"); userComponentBeanDefinition.setLazyInit(true);
// 修改 Bean 的信息 // xxx 非常不推荐 beanFactory.getBean 过早的实例化 Bean UserComponent bean = beanFactory.getBean(UserComponent.class); bean.setUserName("liuzhihang-01"); }}
复制代码


创建自己的 BeanFactoryPostProcessor 并实现 BeanFactoryPostProcessor 接口,添加注解即可。



当然除了实现 BeanFactoryPostProcessor 接口,还有其他接口可以实现:



使用 BeanDefinitionRegistryPostProcessor


BeanDefinitionRegistryPostProcessor 继承了 BeanFactoryPostProcessor,同时扩展了增加了 postProcessBeanDefinitionRegistry 方法。可以支持在 BeanDefinition 注册之后 Bean 实例化之前对 BeanDefinition 进行操作。


@Componentpublic class MyBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {    @Override    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {        // 修改 BeanDefinition 信息        BeanDefinition userComponentBeanDefinition = beanFactory.getBeanDefinition("userComponent");        userComponentBeanDefinition.setLazyInit(true);
// 修改 Bean 的信息 // xxx 非常不推荐 beanFactory.getBean 过早的实例化 Bean UserComponent bean = beanFactory.getBean(UserComponent.class); bean.setUserName("liuzhihang-01"); }
@Override public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
// 注册一个 BeanDefinition BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(OrderComponent.class);
AbstractBeanDefinition orderComponentBeanDefinition = builder.getBeanDefinition();
registry.registerBeanDefinition("orderComponent", orderComponentBeanDefinition);
}}
复制代码


下面是测试代码截图:



OrderComponent 类没有添加任何注解,然后注册为 BeanDefinition 之后,从容器中可以获取到 orderComponent。


如何修改字段属性


在 Spring 文档上说明,非常不建议在 BeanFactoryPostProcessor 中实例化 Bean,那这时候想修改 Bean 的信息,改如何操作?


其实可以通过获取到 MutablePropertyValues 后进行操作:


@Componentpublic class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
@Override public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
// 修改 BeanDefinition 信息 BeanDefinition userComponentBeanDefinition = beanFactory.getBeanDefinition("userComponent"); userComponentBeanDefinition.setLazyInit(true);
MutablePropertyValues userComponentPropertyValues = userComponentBeanDefinition.getPropertyValues();
userComponentPropertyValues.addPropertyValue("userName", "liuzhihang-02");
// 修改 Bean 的信息 // xxx 非常不推荐 beanFactory.getBean 过早的实例化 Bean // UserComponent bean = beanFactory.getBean(UserComponent.class); // bean.setUserName("liuzhihang-01");
}}
复制代码


invokeBeanFactoryPostProcessors


看完前面,我想已经知道了 BeanFactoryPostProcessor 是做什么用的了,而这一步的主要作用就是实例化所有的 BeanFactoryPostProcessor。


进入源码:


protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {    PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
// Detect a LoadTimeWeaver and prepare for weaving, if found in the meantime // (e.g. through an @Bean method registered by ConfigurationClassPostProcessor) if (!IN_NATIVE_IMAGE && beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) { beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory)); beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader())); }}
复制代码


其中 getBeanFactoryPostProcessors 方法获取的是自己添加的 BeanFactoryPostProcessor。这句话是什么意思呢?


public List<BeanFactoryPostProcessor> getBeanFactoryPostProcessors() {    return this.beanFactoryPostProcessors;}
复制代码


看源码,就是直接从 beanFactoryPostProcessors 获取的,那如何向其中添加呢?



其实调用容器的 addBeanFactoryPostProcessor 方法即可。


继续阅读重点代码 invokeBeanFactoryPostProcessors


注意注意,这块代码非常长!


public static void invokeBeanFactoryPostProcessors(        ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {
// Invoke BeanDefinitionRegistryPostProcessors first, if any. Set<String> processedBeans = new HashSet<>();
// 判断是否为 BeanDefinitionRegistry // debug 发现 这里传入的是 DefaultListableBeanFactory // DefaultListableBeanFactory 实现了 BeanDefinitionRegistry if (beanFactory instanceof BeanDefinitionRegistry) { BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
// 创建了两个 List 集合, 用来存放处理器 // BeanDefinitionRegistryPostProcessor 是 BeanFactoryPostProcessor 的子接口 // BeanDefinitionRegistryPostProcessor 还可以额外处理 BeanDefinition, 添加 BeanDefinition // 用法可以参考示例 List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>(); List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();
// 循环 beanFactoryPostProcessors // beanFactoryPostProcessors 是使用 API context.addBeanFactoryPostProcessor 添加进来的 for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
// BeanDefinitionRegistryPostProcessor 要单独添加到 registryProcessors if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) { BeanDefinitionRegistryPostProcessor registryProcessor = (BeanDefinitionRegistryPostProcessor) postProcessor;
// 处理 Bean 的信息 registryProcessor.postProcessBeanDefinitionRegistry(registry); registryProcessors.add(registryProcessor); } else { regularPostProcessors.add(postProcessor); } }
// Do not initialize FactoryBeans here: We need to leave all regular beans // uninitialized to let the bean factory post-processors apply to them! // Separate between BeanDefinitionRegistryPostProcessors that implement // PriorityOrdered, Ordered, and the rest. // 上面循环是执行的我们调用 API 添加的 BeanDefinitionRegistryPostProcessor // 下面执行 Spring 自己的 BeanDefinitionRegistryPostProcessor 集合 // 先执行实现了 PriorityOrdered接口的,然后是 Ordered 接口的,最后执行剩下的 List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();
// First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered. // 第一步先调用 BeanDefinitionRegistryPostProcessors 它实现了PriorityOrdered // 在初始化 reader 时 在注册了 ConfigurationClassPostProcessor 到容器里面 // BeanDefinitionRegistryPostProcessor 实现了 BeanDefinitionRegistryPostProcessor String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false); for (String ppName : postProcessorNames) { if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) { // 添加 bean currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class)); // 这里只添加了名字 后面用来判断谁已经执行过了 processedBeans.add(ppName); } } // 排序 sortPostProcessors(currentRegistryProcessors, beanFactory); registryProcessors.addAll(currentRegistryProcessors);
// 循环执行 processors 的 postProcessBeanDefinitionRegistry 方法 // 这个得在仔细看 // debug 看到 执行完这一步我另一个加 @Component 注解的类 注册到 Registry 里面了 invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry, beanFactory.getApplicationStartup()); // 清除 currentRegistryProcessors.clear();
// Next, invoke the BeanDefinitionRegistryPostProcessors that implement Ordered. // 处理实现 Ordered 的 processor postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false); for (String ppName : postProcessorNames) { // 只有不包含的才执行, 执行完之后会添加进 processedBeans 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, beanFactory.getApplicationStartup()); currentRegistryProcessors.clear();
// Finally, invoke all other BeanDefinitionRegistryPostProcessors until no further ones appear. // 最后执行其他 boolean reiterate = true; while (reiterate) { reiterate = false; postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false); for (String ppName : postProcessorNames) { // 只有不包含的才执行, 执行完之后会添加进 processedBeans 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, beanFactory.getApplicationStartup()); currentRegistryProcessors.clear(); }
// Now, invoke the postProcessBeanFactory callback of all processors handled so far. // 上面处理的都是 postProcessBeanDefinitionRegistry 是在 -> BeanDefinitionRegistryPostProcessor 中 // 下面开始处理 postProcessBeanFactory -> 是在 BeanFactoryPostProcessor 中 invokeBeanFactoryPostProcessors(registryProcessors, beanFactory); invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory); } else { // Invoke factory processors registered with the context instance. // 不是 BeanDefinitionRegistry 则是普通 BeanFactory 直接执行 beanFactoryPostProcessors 即可 invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory); }
// Do not initialize FactoryBeans here: We need to leave all regular beans // uninitialized to let the bean factory post-processors apply to them!
// 第二部分 // 上面执行的是 BeanDefinitionRegistryPostProcessor // 下面开始执行 BeanFactoryPostProcessor String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);
// Separate between BeanFactoryPostProcessors that implement PriorityOrdered, // Ordered, and the rest. // 按照顺序执行 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); } }
// First, invoke the BeanFactoryPostProcessors that implement PriorityOrdered. // 执行实现 PriorityOrdered 的 sortPostProcessors(priorityOrderedPostProcessors, beanFactory); invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);
// Next, invoke the BeanFactoryPostProcessors that implement 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);
// Finally, invoke all other BeanFactoryPostProcessors. List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size()); for (String postProcessorName : nonOrderedPostProcessorNames) { nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class)); } invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);
// Clear cached merged bean definitions since the post-processors might have // modified the original metadata, e.g. replacing placeholders in values... // 清空不必要的元数据信息 beanFactory.clearMetadataCache();}
复制代码


上面总体可以分为两部分:


  1. 执行 BeanDefinitionRegistryPostProcessor 接口里面的两个方法:postProcessBeanDefinitionRegistry 和 postProcessBeanFactory。

  2. 执行 BeanFactoryPostProcessor 接口里面的 postProcessBeanFactory 方法。


以第一部分为例:


  1. 首先判断传入的 BeanFactory 是否为 BeanDefinitionRegistry

1. 声明两个 List 集合,regularPostProcessors 用来存储 BeanFactoryPostProcessor,registryProcessors 用来存储 BeanDefinitionRegistryPostProcessor

1. 循环 beanFactoryPostProcessors,这个就是我们使用 API 方式添加进来的 BeanFactoryPostProcessor。

2. 在循环中 BeanDefinitionRegistryPostProcessor 的 postProcessBeanDefinitionRegistry 会被执行,也就是说我示例的那个添加 BeanDefinition 演示的方法会被执行。

2. 开始执行 Spring 自己的 BeanDefinitionRegistryPostProcessor, 处理顺序为 PriorityOrdered, Ordered, and the rest

1. 循环,将对应的 BeanDefinitionRegistryPostProcessor 添加到 currentRegistryProcessors 集合和 processedBeans 集合表示为已经处理。

2. 排序后添加到第一步的 registryProcessors 中。

3. 调用 invokeBeanDefinitionRegistryPostProcessors 执行所有的 Processor 里面的 postProcessBeanDefinitionRegistry 方法

3. 执行完 1 和 2 之后,所有的 postProcessBeanDefinitionRegistry 已经被执行完了,但是两个集合(registryProcessors、regularPostProcessors)里面的 postProcessBeanFactory 方法还没有被执行。最后会循环执行。

  1. 如果不是 BeanDefinitionRegistry 类型,则直接执行传入的 beanFactoryPostProcessors 即可。


下面是对应的代码截图




以上只是这个方法的前半部分,执行了 BeanDefinitionRegistryPostProcessor 里面的 postProcessBeanDefinitionRegistry 和 postProcessBeanFactory。


因为还有直接实现 BeanFactoryPostProcessor 的处理器,下面则开始处理 BeanFactoryPostProcessor 的处理器。过程和上面类似。


总结


通过以上的阅读,对 invokeBeanFactoryPostProcessors(beanFactory); 这一步方法进行总结。


BeanFactoryPostProcessor 作用


BeanFactoryPostProcessor 主要作用是在注册 BeanDefinition 之后,在 Bean 初始化之前,修改 BeanDefinition 的信息。


BeanFactoryPostProcessor 有个实现叫 BeanDefinitionRegistryPostProcessor,它可以额外的注册新的 BeanDefinition 到容器中。


流程概述


  1. 这一步主要是处理 BeanFactoryPostProcessor,分为两步。

  2. 执行 BeanDefinitionRegistryPostProcessor 接口里面的两个方法:postProcessBeanDefinitionRegistry 和 postProcessBeanFactory。

  3. 执行 BeanFactoryPostProcessor 接口里面的 postProcessBeanFactory 方法。



相关推荐



发布于: 2020 年 12 月 28 日阅读数: 35
用户头像

个人公众号:『 程序员小航 』 2020.07.30 加入

某不知名互联网公司 Java 程序员一枚。记录工作学习中的技术、开发及源码笔记;分享生活中的见闻感悟。

评论

发布
暂无评论
Spring 源码学习 11:invokeBeanFactoryPostProcessors