Spring注解驱动之BeanDefinitionRegistryPostProcessor原理解析

 更新时间:2022年09月30日 09:29:16   作者:融极  
这篇文章主要介绍了Spring注解驱动之BeanDefinitionRegistryPostProcessor原理,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

BeanDefinitionRegistryPostProcessor概述

可以看到BeanDefinitionRegistryPostProcessor是BeanFactoryPostProcessor的子接口。

注释中说执行时机是所有合法的bean定义已经加载,但是还没实例化。

看起来和BeanFactoryPostProcessor执行时机差不多,但是BeanFactoryPostProcessor的注释是所有bean定义被加载,而BeanDefinitionRegistryPostProcessor是所有合法的bean定义。

接着看注释:

This allows for adding further bean definitions before the next post-processing phase kicks in.

意思是BeanDefinitionRegistryPostProcessor允许添加将来的bean定义在下一个后置处理器阶段开始之前。简单说就是还可以往容器中增加新的bean的定义。

因此,大概率BeanDefinitionRegistryPostProcessor的执行顺序在BeanFactoryPostProcessor之前。

案例实践

首先,编写一个类,例如MyBeanDefinitionRegistryPostProcessor,它应要实现BeanDefinitionRegistryPostProcessor这个接口。

package com.meimeixia.ext;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.stereotype.Component;

import com.meimeixia.bean.Blue;

// 记住,我们这个组件写完之后,一定别忘了给它加在容器中
@Component
public class MyBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {

	@Override
	public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
		// TODO Auto-generated method stub
		System.out.println("MyBeanDefinitionRegistryPostProcessor...bean的数量:" + beanFactory.getBeanDefinitionCount());
	}

	/**
	 * 这个BeanDefinitionRegistry就是Bean定义信息的保存中心,这个注册中心里面存储了所有的bean定义信息,
	 * 以后,BeanFactory就是按照BeanDefinitionRegistry里面保存的每一个bean定义信息来创建bean实例的。
	 * 
	 * bean定义信息包括有哪些呢?有这些,这个bean是单例的还是多例的、bean的类型是什么以及bean的id是什么。
	 * 也就是说,这些信息都是存在BeanDefinitionRegistry里面的。
	 */
	@Override
	public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
		// TODO Auto-generated method stub
		System.out.println("postProcessBeanDefinitionRegistry...bean的数量:" + registry.getBeanDefinitionCount());
		// 除了查看bean的数量之外,我们还可以给容器里面注册一些bean,我们以前也简单地用过
		/*
		 * 第一个参数:我们将要给容器中注册的bean的名字
		 * 第二个参数:BeanDefinition对象
		 */
		// RootBeanDefinition beanDefinition = new RootBeanDefinition(Blue.class); // 现在我准备给容器中添加一个Blue对象
		// 咱们也可以用另外一种办法,即使用BeanDefinitionBuilder这个构建器生成一个BeanDefinition对象,很显然,这两种方法的效果都是一样的
		AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.rootBeanDefinition(Blue.class).getBeanDefinition();
		registry.registerBeanDefinition("hello", beanDefinition);
	}
}

测试结果

可以看到,BeanDefinitionRegistryPostProcessor里面的两个方法,postProcessBeanDefinitionRegistry在postProcessBeanFactory之前执行。

BeanDefinitionRegistryPostProcessor比BeanFactoryPostProcessor先执行。

源码分析

自己在测试示例中方法打断点,然后查看调用栈即可,下面是一些主要的代码片段。

继续向下看,可以看到会取出所有实现了BeanDefinitionRegistryPostProcessor接口的类,即从容器中获取到所有的BeanDefinitionRegistryPostProcessor组件。

然后,优先调用实现了PriorityOrdered接口的BeanDefinitionRegistryPostProcessor组件。

点进去这个方法里面一看究竟,原来是先调用完BeanDefinitionRegistryPostProcessor组件里面的postProcessBeanDefinitionRegistry方法,然后再来调用它里面的postProcessBeanFactory方法。

我们再来仔细看一下PostProcessorRegistrationDelegate类中的invokeBeanFactoryPostProcessors方法,只不过这时是从程序停留的地方(即第122行代码处)往下看,如下图所示。

小结

BeanDefinitionRegistryPostProcessor的执行流程。

1. 创建IOC容器。

2. 调用refresh方法。

3. 从IOC容器中获取所有的BeanDefinitionRegistryPostProcessor组件,并依次触发它们的postProcessBeanDefinitionRegistry方法,之后触发它的postProcessBeanFactory方法。

4. 从IOC容器中获取到所有的BeanFactoryPostProcessor组件,并依次触发它们的postProcessBeanFactory方法。

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • MybatisPlus如何自动生成映射文件

    MybatisPlus如何自动生成映射文件

    这篇文章主要介绍了MybatisPlus如何自动生成映射文件,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-01-01
  • Spring内置任务调度如何实现添加、取消与重置详解

    Spring内置任务调度如何实现添加、取消与重置详解

    任务调度是我们日常开发中经常会碰到的,下面这篇文章主要给大家介绍了关于Spring内置任务调度如何实现添加、取消与重置的相关资料,文中通过示例代码介绍的非常详细,需要的朋友可以参考借鉴,下面随着小编来一起学习学习吧。
    2017-10-10
  • SpringBoot3整合Druid监控功能的项目实践

    SpringBoot3整合Druid监控功能的项目实践

    Druid连接池作为一款强大的数据库连接池,提供了丰富的监控和管理功能,成为很多Java项目的首选,本文主要介绍了SpringBoot3整合Druid监控功能的项目实践,感兴趣的可以了解一下
    2024-01-01
  • Java棋类游戏实践之中国象棋

    Java棋类游戏实践之中国象棋

    这篇文章主要为大家详细介绍了Java棋类游戏中的中国象棋实现方法,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2016-02-02
  • java本机内存分配Native memory allocation mmap失败问题解决

    java本机内存分配Native memory allocation mmap失败问题解决

    这篇文章主要介绍了java本机内存分配Native memory allocation mmap失败问题解决,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-11-11
  • SpringBoot 热搜与不雅文字过滤的实现

    SpringBoot 热搜与不雅文字过滤的实现

    本文主要介绍了SpringBoot 热搜与不雅文字过滤的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-07-07
  • 关于log4j漏洞修复解决方案及源码编译

    关于log4j漏洞修复解决方案及源码编译

    Log4j 是Apache为Java提供的日志管理工具。他与System.out.println()的作用相似,用来跟踪、调试、维护程序。这篇文章主要介绍了关于log4j漏洞修复解决方案及源码编译,需要的朋友可以参考下
    2021-12-12
  • java 中cookie的详解及简单实例

    java 中cookie的详解及简单实例

    这篇文章主要介绍了java 中cookie的详解及简单实例的相关资料,这里对cookie 的建立与读取,和设定cookie 生命周期等详细介绍,需要的朋友可以参考下
    2017-01-01
  • Java基本概念监视器实习原理解析

    Java基本概念监视器实习原理解析

    这篇文章主要介绍了Java基本概念监视器实习原理解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-08-08
  • Springboot项目优雅地处理日志的方法详解

    Springboot项目优雅地处理日志的方法详解

    这篇文章主要介绍了Springboot项目---优雅地处理日志,本文通过实例图文相结合给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-07-07

最新评论