Bean实例化之前修改BeanDefinition示例详解
作者:刨红薯的小羊竿尔 发布时间:2023-10-26 23:31:09
BeanFactory
BeanFactory是Spring中容器功能的基础,用于存放所有已经加载的bean,为了保证程序上的高可扩展性,Spring针对BeanFactory做了大量的扩展。BeanFactoryPostProcessor是BeanFactory的后置处理器;比如在postProcessBeanFactory方法中,可以获取BeanDefinition的相关对象,并且修改该对象的属性。
@FunctionalInterface
public interface BeanFactoryPostProcessor {
void postProcessBeanFactory(ConfigurableListableBeanFactory var1) throws BeansException;
}
通过BeanDefinition对象实例化Bean对象
Spring IOC在实例化Bean对象之前,需要先读取Bean的相关属性,保存到BeanDefinition
对象中,然后通过BeanDefinition对象,实例化Bean对象。如果我们需要修改BeanDefinition对象中的属性,就可以实现BeanFactoryPostProcessor接口,重写postProcessBeanFactory方法进行自定义,是不是很方便呢。
@Component
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
DefaultListableBeanFactory defaultListableBeanFactory = (DefaultListableBeanFactory) configurableListableBeanFactory;
BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(User.class);
beanDefinitionBuilder.addPropertyValue("id", 123456);
beanDefinitionBuilder.addPropertyValue("label", "技术那些事儿");
defaultListableBeanFactory.registerBeanDefinition("user", beanDefinitionBuilder.getBeanDefinition());
}
}
BeanFactoryPostProcessor使用目的:在BeanFactory标准初始化之后调用,用来定制和修改BeanFactory的内容;
BeanFactoryPostProcessor工作时机:所有的bean定义已经保存加载到beanFactory中,但bean的实例还没创建;
BeanFactoryPostProcessor和BeanPostProcessor类似,可以对beanDefinition进行处理,也就是说SpringIOC容器允许BeanFactoryPostProcessor在容器实际实例化任何bean之前读取beanDefinition,并有可能修改它。并且我们还可以配置自定义的BeanFactoryPostProcessor,如果想改变bean,那么使用beanPostProcessor。
并可以通过order属性来控制BeanFactoryPostProcessor的执行次序;因为只有实现了Ordered接口时,才可以设置这个属性,所以在实现BeanFactoryPostProcessor的时候,就应该考虑实现Ordered接口。
BeanFactoryPostProcessor的作用域是容器级的,只和你使用的容器有关,如果在一个容器中定义了一个BeanFactoryPostProcessor,它仅仅对此容器中的beanDefinition进行后处理。BeanFactoryPostProcessor不会对定义在另一个容器中的bean进行后处理,即便这两个容器都在同一个层次上。
BeanFactoryPostProcessor还有一个子接口BeanDefinitionRegistryPostProcessor,其内部添加了一个方法postProcessBeanDefinitionRegistry:
void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException;
ConfigurationClassPostProcessor这个类非常重要,其实现了BeanDefinitionRegistryPostProcessor接口与PriorityOrdered接口:
public class ConfigurationClassPostProcessor implements BeanDefinitionRegistryPostProcessor,
PriorityOrdered, ResourceLoaderAware, BeanClassLoaderAware, EnvironmentAware
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
int registryId = System.identityHashCode(registry);
if (this.registriesPostProcessed.contains(registryId)) {
throw new IllegalStateException(
"postProcessBeanDefinitionRegistry already called on this post-processor against " + registry);
}
if (this.factoriesPostProcessed.contains(registryId)) {
throw new IllegalStateException(
"postProcessBeanFactory already called on this post-processor against " + registry);
}
this.registriesPostProcessed.add(registryId);
/**
* @author lcy
* 处理配置beanDefinition
*/
processConfigBeanDefinitions(registry);
}
就是在这个方法里将配置类指定的类解析为BeanDefinition对象,并放入BeanFactory的beanDefinitionMap中。还有一点需要说明,这个类是在执行AnnotationConfigApplicationContext的无参构造方法时被解析为beanDefinition并放入map中的。在AnnotationConfigApplicationContext的refresh()内部的 invokeBeanFactoryPostProcessors(beanFactory)方法完成了对 BeanFactoryPostProcessor对象与BeanDefinitionRegistryPostProcessor对象相关方法的执行。
来源:https://juejin.cn/post/7179241069651951653
猜你喜欢
- classpath读取resources目录下文件最近在springboot+maven的项目中去读取资源文件的时候,报了找不到文件的错误。
- 本文实例为大家分享了Java猜拳游戏的具体代码,供大家参考,具体内容如下先来看一下效果图: 首先我们创建一个Person类,这个类
- 本文实例讲述了C#实现获取程序路径方法。分享给大家供大家参考。具体如下:获取DLL的目录:Assembly myAssembly = Ass
- 指针的概念:指针是一个特殊的变量,它里面存储的数值被解释成为内存里的一个地址。要搞清一个指针需要搞清指针的四方面的内容:指针的类型,指针所指
- SpringDataJpa创建中间表//fetch=FetchType.EAGER 关闭懒加载 相当于hibernate中的lazy=fal
- 在前面我们已经完成了ActiveX控件的开发,接下来的就是发布它了。  
- 一、泛型1.1 泛型类的定义// 1. 尖括号 <> 是泛型的标志// 2. E 是类型变量(Type Variable),变量
- 一、 HttpURLConnection以GET方式访问网络:HttpURLConnection connection = null;try
- 简单工厂模式解释: 简单工厂模式(Simple Fact
- 本文实例讲述了Android编程基于自定义View实现绚丽的圆形进度条功能。分享给大家供大家参考,具体如下:本文包含两个组件,首先上效果图:
- 使用idea创建javaweb项目idea还是写框架项目比较爽,原生的javaweb项目不是特别方便,这篇文章就是记录一下创建的过程图较多注
- java 进制转换实例详解十进制转成十六进制:  
- 1 背景与动机通常,如果只想用C#在控制台上打印一行“Hello World!”,这可不是Console.WriteLine("H
- C#备忘录设计模式大家好,老胡又和大家见面了。首先承认今天的博客有点标题党了,人生是没有存档,也没有后悔药的。有存档和后悔药的,那是游戏,不
- Spring 封装了 RedisTemplate 来操作 Redis,它支持所有的 Redis 原生的 API。在 Re
- 先对问题进行描述:(1)在MyEclipse Servers视图在MyEclipse 10.7.0在某些情况下,可能无法打开。 试图打开视图
- 本文实例展示了C#自定义函数NetxtString实现生成随机字符串的方法,在进行C#项目开发中非常实用!分享给大家供大家参考。一、生成随机
- 问题描述:某天打开项目的activity的java文件界面突然变成下面这样了,但是用Notepad++打开代码什么的都正常,不知道什么原因造
- Android 应用坐标系详解:
- 目录重入锁1. 实现重进入2. 公平与非公平获取锁的区别读写锁1. 接口示例2. 读写状态的设计3. 写锁的获取与释放4. 读锁的获取与释放