Bean的生命周期

2023-09-18 19:08:53
Spring Bean 的生命周期是从 Bean 实例化之后,即通过反射创建出对象之后,到 Bean 成为一个完整对象,最终存储到单例池中,这个过程被称为Spring Bean 的生命周期。

小枫叶 


一,实例化

1.1Bean工厂后处理器 – BeanFactoryPostProcessor

BeanFactoryPostProcessor 是一个接口规范,实现了该接口的类只要交由 Spring 容器管理的话,那么 Spring就会回调该接口的方法,用于对BeanDefinition 注册 修改 的功能。

1.1.1修改Bean

修改已经经过加载xml配置文件,解析获取配置中的每个的信息,封装成一个个的BeanDefinition对象====》存储在名为beanDefinitionMapMap<String,BeanDefinition>中。

public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {@Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        System.out.println("MyBeanFactoryPostProcessor的postProcessBeanFactory");
        BeanDefinition beanDefinition=beanFactory.getBeanDefinition("user");
        beanDefinition.setBeanClassName("com.apesource.pojo.Student");}
}

applicationcontext.xml中的内容。

<bean class="com.apesource.pojo.User" id="user">
</bean>
<bean class="com.apesource.processor.MyBeanFactoryPostProcessor"></bean>

//运行结果 

MyBeanFactoryPostProcessor的postProcessBeanFactory
com.apesource.pojo.Student@1ed4004b

//结果分析

注册的是user的bean,但是经过BeanFactoryPostProcessor重新将BeanclassName修改过后,变成了student的bean。

1.1.2 注册一个Bean的方法一

如何利用BeanFactoryPostProcessor注册一个Bean

//注册演示
        BeanDefinition beanDefinition1 = new RootBeanDefinition();
        beanDefinition1.setBeanClassName("com.apesource.pojo.Student");
//强转成DefaultListableBeanFactory
        DefaultListableBeanFactory defaultListableBeanFactory =              (DefaultListableBeanFactory) beanFactory;
        defaultListableBeanFactory.registerBeanDefinition("stu2",beanDefinition1);

在xml中并没有注册stu2,但是在getBean的时候,可以得到student的实体类对象

1.1.3 注册一个Bean的方法二 

Bean工厂后处理器 – BeanDefinitionRegistryPostProcessor 

Bean 工厂后处理器 – BeanDefinitionRegistryPostProcessor Spring 提供了一个 BeanFactoryPostProcessor 的子接口 BeanDefinitionRegistryPostProcessor 专门用
于注册 BeanDefinition 操作。
public class MyBeanFactoryPostProcessor2 implements
BeanDefinitionRegistryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory
configurableListableBeanFactory) throws BeansException {}
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry
beanDefinitionRegistry) throws BeansException {
BeanDefinition beanDefinition = new RootBeanDefinition();
beanDefinition.setBeanClassName("com.apesource.pojo.Student");
beanDefinitionRegistry.registerBeanDefinition("stu",beanDefinition);
}
}

Bean被实例化后,会经过初始化

二,初始化

2.1BeanPostProcessor(Bean后处理)

BeanPostProcessor,是 Bean 后处理。
//1.自定义MyBeanPostProcessor
public class MyBeanPostProcessor implements BeanPostProcessor {
/* 参数: bean是当前被实例化的Bean,beanName是当前Bean实例在容器中的名称
返回值:当前Bean实例对象 */
public Object postProcessBeforeInitialization(Object bean, String beanName)
throws BeansException {
System.out.println("BeanPostProcessor的before方法...");
return bean;
}
/* 参数: bean是当前被实例化的Bean,beanName是当前Bean实例在容器中的名称
返回值:当前Bean实例对象 */
public Object postProcessAfterInitialization(Object bean, String beanName)
throws BeansException {
System.out.println("BeanPostProcessor的after方法...");
return bean;
}
}
//2.注入配置MyBeanPostProcessor
<bean class="com.apesource.processors.MyBeanPostProcessor"></bean>
//3.测试控制台打印结果如下
User创建了...
BeanPostProcessor的before方法...
User属性填充...
User初始化方法执行...
BeanPostProcessor的after方法...
com.apesource.pojo.User@56ac3a89

2.2属性初始化

2.2.1解决双向对象冲突(三级缓存)

//1 、最终存储单例 Bean 成品的容器,即实例化和初始化都完成的 Bean ,称之为 " 一级缓存 "
Map < String , Object > singletonObjects = new ConcurrentHashMap ( 256 );
//2 、早期 Bean 单例池,缓存半成品对象,且当前对象已经被其他对象引用了,称之为 " 二级缓存 "
Map < String , Object > earlySingletonObjects = new ConcurrentHashMap ( 16 );
//3 、单例 Bean 的工厂池,缓存半成品对象,对象未被引用,使用时在通过工厂创建 Bean ,称之为 " 三级缓存"。
Map < String , ObjectFactory <?>> singletonFactories = new HashMap ( 16 );
  1. UserService 实例化对象,但尚未初始化,将UserService存储到三级缓存;
  2. UserService 属性注入,需要UserDao,从缓存中获取,没有UserDao
  3. UserDao实例化对象,但尚未初始化,将UserDao存储到到三级缓存;
4.将出现矛盾的两个Bean,其中一个Bean(UserDao)要走另一条路径,完成自己的初始化。 从三级缓存到二级,最终到一级缓存, 供UserService调用。
最终缓存到名为singletonObjects 单例池。

三,调用

getBean方法可以获取到serviceBean。getBean最终得到的都是完整的Bean

四,销毁 

更多推荐

vue模板语法(下集)

事件处理器Vue模板语法中的事件处理器是指在Vue组件中绑定DOM事件,当事件发生时执行相应的方法或表达式。常见的事件包括点击事件@click、输入事件@input、鼠标移入事件@mouseover等等。事件监听可以使用v-on指令2.1事件修饰符.Vue通过由点(.)表示的指令后缀来调用修饰符,.stop.preve

华为OD机试 - 矩形相交的面积 - 逻辑分析(Java 2023 B卷 100分)

目录专栏导读一、题目描述二、输入描述三、输出描述1、输入:2、输出:3、说明四、解题思路五、Java算法源码六、效果展示1、输入2、输出3、说明华为OD机试2023B卷题库疯狂收录中,刷题点这里专栏导读本专栏收录于《华为OD机试(JAVA)真题(A卷+B卷)》。刷的越多,抽中的概率越大,每一题都有详细的答题思路、详细的

高并发压力测试,你真的会做吗?

一、Introduction对于小微企业网站在自主推出某些活动时,可能导致网站产生高并发访问的情况。针对这种情况采用临时租用云服务器是有性价比的应对措施,比如,使用弹性云。这种租用服务有的按照访问流量计费。为了计算出大概的预算,需要根据推算的访问量做并发压力测试。二、压力测试方法一般,使用apache自带的ab.exe

【Java】泛型

简单泛型促成泛型出现的最主要的动机之一是为了创建集合类,我们先看一个只能持有单个对象的类。这个类可以明确指定其持有的对象的类型://generics/Holder1.javaclassAutomobile{}publicclassHolder1{privateAutomobilea;publicHolder1(Auto

解决文件只能在windows系统上传成功,而linux系统上传失败。

场景:在我们项目准备上线进行SIT测试的时候,测试在文件上传的时候,一直上传不成功,表示当前文件不支持上传,然后我们让测试将他的文件发送给我们进行测试,我们是能够上传成功的,然后询问他们使用的什么系统,发现他们使用的是Linux发行版操作系统Ubuntu。分析原因:可能是由于Linux和Windows操作系统在处理文件

ES6之Map和Set有什么不同?

一、Map1.定义Map是ES6提供的一种新的数据结构,它是键值对的集合,类似于对象,但是键的范围不限于字符串,各种类型的值都可以当做键。Object结构是“字符串-值”的对应,Map结构则是“值-值”的对应2.代码示例Map本身是一个构造函数,先来生成一个Map数据结构,从打印的结果就可以看出,Map实例有以下属性和

C#,《小白学程序》第二十三课:大数的除法(BigInteger Divide)

1文本格式///<summary>///比较a,b的大小,返回1,0,-1///数据从低位(右)往高位(左)存储;///</summary>///<paramname="a"></param>///<paramname="b"></param>///<returns></returns>publicstaticintb

pytorch的卷积层池化层和非线性变化 和机器学习线性回归

卷积层:两个输出的情况就会有两个通道可以改变通道数的最简单的神经网络结构:nn.Mudule就是继承父类super执行的是先执行父类函数里面的forward执行的就是前向网络,就是往前推进的,当然也有反向转播,那就是用来就gradientdicent了,求导计算了。卷积后的结果展示:这里有个小细节224*244输出22

优化软件系统,解决死锁问题,提升稳定性与性能 redis排队下单

项目背景:随着用户数量的不断增加,我们的速卖通小管家软件系统面临了一个日益严重的问题:在从存储区提供程序的数据读取器中进行读取时,频繁出现错误。系统报告了一个内部异常:异常信息如下:从存储区提供程序的数据读取器中进行读取时出错。有关详细信息,请参阅内部异常。--->System.Data.SqlClient.SqlEx

单例模式优缺点

单例模式是一种创建型设计模式,其主要目的是确保类只有一个实例,并提供全局访问点来获取该实例。单例模式具有一些优点和缺点,下面我将列出它们:**优点:**1.**全局唯一性**:单例模式确保在应用程序中只有一个实例,这对于某些类来说是非常有用的,例如配置管理、日志记录器、数据库连接等。2.**延迟初始化**:单例模式允许

网页的快捷方式打开自动全屏--Chrome、Firefox 浏览器相关设置

Firefox的全屏方式与Chrome不同,Chrome自带全屏模式以及APP模式,通过简单的参数即可设置,而Firefox暂时么有这个功能,Firefox的全屏功能可以通过全屏插件实现。全屏模式下,按F11不会退出全屏,鼠标移动到屏幕上方也不会提示退出全屏如果当前运行着其它的Chrome窗口,那么全屏化打开是无效的,

热文推荐