- Bean的生命周期
- Bean的生命周期之5步
- Bean的生命周期之7步
- Bean的生命周期之10步
八、★★★Bean的生命周期
8.1 什么是Bean的生命周期
Bean
的生命周期就是:对象从创建开始到最终销毁的整个过程,Bean
对象从创建到销毁中经历了哪些过程。- 什么时候创建
Bean
对象? - 创建
Bean
对象的前后会调用什么方法? Bean
对象什么时候销毁?Bean
对象的销毁前后调用什么方法?
- 什么时候创建
- Spring 其实就是一个管理
Bean
对象的工厂,它负责对象的创建,对象的销毁等。
8.2 为什么要知道Bean的生命周期
- 生命周期的本质是:在哪个时间节点上调用了哪个类的哪个方法。
- 我们需要充分了解在这个生命线上,都有哪些特殊的时间节点,在这些特殊节点会调用哪个类的哪个方法。
- 我们可能需要在某个特殊的时间点上执行一段特定的代码,只有我们知道了特殊的时间节点都在哪,在该特殊节点会调用什么方法,我们才可以确定代码写到哪,这段代码就可以放到这个节点上,当生命线走到这里的时候,自然会被调用。
8.3 Bean的生命周期之5步
Bean
生命周期可以粗略的划分为五大步:- 第一步:实例化
Bean
,调用无参构造方法创建对象。 - 第二步:
Bean
属性赋值,调用对象的set
方法,进行set
注入。 - 第三步:初始化
Bean
,调用Bean
的initBean
方法(该方法需要自己写,然后进行配置)。 - 第四步:使用
Bean
。 - 第五步:销毁
Bean
,调用Bean
的destroyBean
方法(该方法需要自己写,然后进行配置)。- 进行
Bean
的销毁,必须关闭 Spring 容器,只有关闭了 Spring 容器,Bean
才会进行销毁。
- 进行

- 第一步:实例化
1 | package com.f.spring6.bean; |
1 |
|
1 | public void testBeanLifeCycleFive() { |
8.4 Bean的生命周期之7步
Bean
生命周期七步,相较于Bean
生命周期五步,在初始化Bean
的前和后,添加了两步。在
Bean
生命周期之 5 步中,第 3 步是初始化Bean
,在初始化前和初始化后执行的方法为 “Bean后处理器” 的before
和after
方法,通过 “Bean后处理器”,我们可以在初始化Bean
的前后添加需要执行的代码。要添加 “Bean后处理器”,需要类实现
BeanPostProcessor
类,并且重写before
和after
方法。Bean
生命周期之 7 步:- 第一步:实例化
Bean
。 - 第二步:
Bean
属性赋值。 - 第三步:执行 “Bean后处理器” 的
before
方法。 - 第四步:初始化
Bean
。 - 第五步:执行 “Bean后处理器” 的
after
方法。 - 第六步:使用
Bean
。 - 第七步:销毁
Bean
。

- 第一步:实例化
添加 “Bean后处理器”。
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
27package com.f.spring6.bean;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
/**
* @author fzy
* @date 2024/1/21 13:05
*/
public class LogBeanPostProcessor implements BeanPostProcessor {
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("执行Bean后处理器的before方法");
// return 不要修改
return BeanPostProcessor.super.postProcessBeforeInitialization(bean, beanName);
}
// 方法有两个参数:
// 第一个参数:刚创建的Bean对象
// 第二个参数:Bean的名字
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("执行Bean后处理器的after方法");
// return 不要修改
return BeanPostProcessor.super.postProcessAfterInitialization(bean, beanName);
}
}配置 “Bean后处理器”。
1
2
3
4
5
6
7
8
9
10
11
12
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<!--配置Bean后处理器-->
<!--注意:这个Bean后处理器将作用于整个配置文件中所有的Bean-->
<bean class="com.f.spring6.bean.LogBeanPostProcessor"/>
<!--需要手动指定初始化方法和销毁方法-->
<bean id="user" class="com.f.spring6.bean.User" init-method="initBean" destroy-method="destroyBean">
<property name="name" value="jack"/>
</bean>
</beans>- 注意:这个 “Bean后处理器”将作用于整个配置文件中所有的
Bean
。
- 注意:这个 “Bean后处理器”将作用于整个配置文件中所有的
这样,如果执行的还是之前的测试方法:
1
2
3
4
5
6
7
8public void testBeanLifeCycleFive() {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");
User user = applicationContext.getBean("user", User.class);
System.out.println("第四步:使用Bean:" + user);
// 注意:必须手动关闭Spring容器,这样Spring容器才会销毁Bean
ClassPathXmlApplicationContext context = (ClassPathXmlApplicationContext) applicationContext;
context.close();
}会发现输出结果多了两步:
1
2
3
4
5
6
7第一步:无参数构造方法执行
第二步:给对象的属性赋值
执行Bean后处理器的before方法
第三步:初始化Bean
执行Bean后处理器的after方法
第四步:使用Bean:com.f.spring6.bean.User@4c402120
第五步:销毁Bean
8.5 Bean的生命周期之10步
Bean
生命周期十步比七步多的三步:- 点位1:在 “Bean后处理器”
before
方法之前,在Bean
属性赋值之后。 - 点位2:在 “Bean后处理器”
before
方法之后,在Bean
的初始化之前。 - 点位3:使用
Bean
之后,或者说销毁Bean
之前。
添加的这三个点位的特点:都是在检查你这个
Bean
是否实现了某些特定的接口,如果实现了这些接口,则 Spring 容器会调用这个接口中的方法。
- 点位1:在 “Bean后处理器”
8.5.1 实现Aware相关接口
Aware
相关的接口包括:BeanNameAware
、BeanClassLoaderAware
、BeanFactoryAware
。- 当
Bean
实现了BeanNameAware
,Spring 会将Bean
的名字传递给Bean
。 - 当
Bean
实现了BeanClassLoaderAware
,Spring 会将加载该Bean
的类加载器传递给Bean
。 - 当
Bean
实现了BeanFactoryAware
,Spring 会将Bean
工厂对象传递给Bean
。
- 当
在 “Bean后处理器”
before
方法之前,会检查Bean
是否实现了Aware
相关的接口,如果实现了接口则调用这些接口中的方法。调用这些方法的目的是为了给你传递一些数据,让你更加方便使用。
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
30package com.f.spring6.bean;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanClassLoaderAware;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.BeanNameAware;
/**
* @author fzy
* @date 2024/1/21 12:47
*/
public class User implements BeanNameAware, BeanClassLoaderAware, BeanFactoryAware {
...
public void setBeanClassLoader(ClassLoader classLoader) {
System.out.println("Bean的类加载器:" + classLoader);
}
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
System.out.println("生产Bean的工厂:" + beanFactory);
}
public void setBeanName(String name) {
System.out.println("Bean的名字:" + name);
}
}1
2
3
4
5
6
7
8
9
10第一步:无参数构造方法执行
第二步:给对象的属性赋值
Bean的名字:user
Bean的类加载器:jdk.internal.loader.ClassLoaders$AppClassLoader@63947c6b
生产Bean的工厂:org.springframework.beans.factory.support.DefaultListableBeanFactory@77167fb7: defining beans [com.f.spring6.bean.LogBeanPostProcessor#0,user]; root of factory hierarchy
执行Bean后处理器的before方法
第三步:初始化Bean
执行Bean后处理器的after方法
第四步:使用Bean:com.f.spring6.bean.User@1165b38
第五步:销毁Bean
8.5.2 实现InitializingBean接口
在
Bean
初始化之前,Spring 会检查Bean
是否实现了InitializingBean
接口,如果实现了,则调用接口中的方法。InitializingBean
的方法早于init-method
的执行。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17package com.f.spring6.bean;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.*;
/**
* @author fzy
* @date 2024/1/21 12:47
*/
public class User implements BeanNameAware, BeanClassLoaderAware, BeanFactoryAware, InitializingBean {
...
public void afterPropertiesSet() throws Exception {
System.out.println("InitializingBean的afterPropertiesSet方法执行...");
}
}1
2
3
4
5
6
7
8
9
10
11第一步:无参数构造方法执行
第二步:给对象的属性赋值
Bean的名字:user
Bean的类加载器:jdk.internal.loader.ClassLoaders$AppClassLoader@63947c6b
生产Bean的工厂:org.springframework.beans.factory.support.DefaultListableBeanFactory@77167fb7: defining beans [com.f.spring6.bean.LogBeanPostProcessor#0,user]; root of factory hierarchy
执行Bean后处理器的before方法
InitializingBean的afterPropertiesSet方法执行...
第三步:初始化Bean
执行Bean后处理器的after方法
第四步:使用Bean:com.f.spring6.bean.User@4c12331b
第五步:销毁Bean
8.5.3 实现DisposableBean接口
在销毁
Bean
之前,检查Bean
是否实现了DisposableBean
接口,如果实现了,则调用接口中的方法。DisposableBean
的方法destroy()
早于destroy-method
的执行。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17package com.f.spring6.bean;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.*;
/**
* @author fzy
* @date 2024/1/21 12:47
*/
public class User implements BeanNameAware, BeanClassLoaderAware, BeanFactoryAware, InitializingBean, DisposableBean {
...
public void destroy() throws Exception {
System.out.println("DisposableBean的destroy方法执行...");
}
}1
2
3
4
5
6
7
8
9
10
11
12第一步:无参数构造方法执行
第二步:给对象的属性赋值
Bean的名字:user
Bean的类加载器:jdk.internal.loader.ClassLoaders$AppClassLoader@63947c6b
生产Bean的工厂:org.springframework.beans.factory.support.DefaultListableBeanFactory@77167fb7: defining beans [com.f.spring6.bean.LogBeanPostProcessor#0,user]; root of factory hierarchy
执行Bean后处理器的before方法
InitializingBean的afterPropertiesSet方法执行...
第三步:初始化Bean
执行Bean后处理器的after方法
第四步:使用Bean:com.f.spring6.bean.User@7586beff
DisposableBean的destroy方法执行...
第五步:销毁Bean
8.6 Bean的作用域不同,管理方式不同
Spring 会根据
Bean
的作用域来选择不同的管理方式。对于
singleton
作用域的Bean
,Spring 能够精确地知道该Bean
何时被创建,何时初始化完成,以及何时被销毁。而对于
prototype
作用域的Bean
,Spring 只负责创建,当容器创建了Bean
的实例后,对该Bean
初始化完毕,等到客户端程序获取到该Bean
之后,Bean
的实例就交给客户端代码管理,Spring 容器将不再跟踪其生命周期。- 因此,Spring 容器只对
singleton
的Bean
进行完整的生命周期管理,对于prototype
的Bean
,Spring 只进行部分的生命周期管理。
- 因此,Spring 容器只对
8.7 自己new的对象如何让Spring管理
有些时候可能会遇到这样的需求,某个 java 对象是我们自己
new
的,然后我们希望这个对象被 Spring 容器管理。- 该怎么让我们自己
new
的对象让 Spring 容器管理呢?
1
2
3
4
5
6
7
8package com.f.spring6.bean;
/**
* @author fzy
* @date 2024/1/21 13:55
*/
public class Student {
}1
2
3
4
5
6
7
8
9
10
11
12
public void testRegisterBean() {
// 自己new的对象
Student student = new Student();
System.out.println("纳入Spring管理前的Student对象:" + student);
// 将以上自己new的对象纳入Spring容器来管理
DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
factory.registerSingleton("studentBean", student);
// 从Spring容器中获取
Student studentBean = factory.getBean("studentBean", Student.class);
System.out.println("纳入Spring管理后的StudentBean:" + studentBean);
}1
2纳入Spring管理前的Student对象:com.f.spring6.bean.Student@1cd072a9
纳入Spring管理后的StudentBean:com.f.spring6.bean.Student@1cd072a9- 发现是同一个对象,说明该对象已经纳入 Spring 容器管理了。
- 该怎么让我们自己