Spring Bean生命周期

1.Spring中bean的生命周期

在spring中,bean是spring IOC容器实例化、组装和管理的对象,因此spring中的bean的生命周期也由spring管理。

bean的生命周期分为4个阶段为:

  • 实例化 - Instantiation
  • 初始化 - Populate
  • 使用 - Initialization
  • 销毁 - Destruction

2.Bean的生命周期图

3.代码测试

3.1 Person

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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
package com.xxx.beancycle.instant;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.BeanNameAware;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;


@Component
public class Person implements InitializingBean, DisposableBean {

private String name;
private String address;
private int phone;

public Person() {
System.out.println("【构造器】调用Person的构造器实例化");
}

public String getName() {
return name;
}

public void setName(String name) {
System.out.println("【注入属性】注入属性name:" + name);
this.name = name;
}

public String getAddress() {
return address;
}

public void setAddress(String address) {
System.out.println("【注入属性】注入属性address:"+address);
this.address = address;
}

public int getPhone() {
return phone;
}

public void setPhone(int phone) {
System.out.println("【注入属性】注入属性phone:"+ phone);
this.phone = phone;
}

@Override
public String toString() {
return "Person [address=" + address + ", name=" + name + ", phone="
+ phone + "]";
}

//@PostConstruct-->InitializingBean接口方法(afterPropertiesSet)-->自定义的方法
@PostConstruct
public void PostConstruct(){
System.out.println("PostConstruct!!");
}

// 这是InitializingBean接口方法
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("=================="+this);
System.out.println("【InitializingBean接口】调用InitializingBean.afterPropertiesSet()");
}

// 通过<bean>的init-method属性指定的初始化方法
public void myInit() {
System.out.println("【init-method】调用<bean>的init-method属性指定的初始化方法");
}


//@PreDestroy-->DiposibleBean接口方法(destroy)-->自定义的方法
@PreDestroy
public void PreDestroy(){
System.out.println("PreDestroy!!");
}

//这是DiposibleBean接口方法
@Override
public void destroy() throws Exception {
System.out.println("【DiposibleBean接口】调用DiposibleBean.destory()");
}

// 通过<bean>的destroy-method属性指定的初始化方法
public void myDestory() {
System.out.println("【destroy-method】调用<bean>的destroy-method属性指定的初始化方法");
}


}

三个属性:name、address、phone。且分别有3个方法@PostConstruct、afterPropertiesSet()、myInit()。针对于bean的初始化方法。同理,有3个方法对应bean销毁调用的方法。

3.2 MyBeanPostProcessor

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class MyBeanPostProcessor implements BeanPostProcessor {

public MyBeanPostProcessor() {
super();
System.out.println("这是BeanPostProcessor实现类构造器!!");
}

@Override
public Object postProcessAfterInitialization(Object arg0, String arg1) throws BeansException {
System.out.println("BeanPostProcessor接口方法postProcessAfterInitialization对属性1进行更改!");
return arg0;
}

@Override
public Object postProcessBeforeInitialization(Object arg0, String arg1) throws BeansException {
System.out.println("BeanPostProcessor接口方法postProcessBeforeInitialization对属性1进行更改!");
return arg0;
}
}

实现BeanPostProcessor接口,覆写postProcessBeforeInitialization、postProcessAfterInitialization方法。

3.3 MyInstantiationAwareBeanPostProcessor

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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
public class MyInstantiationAwareBeanPostProcessor extends
InstantiationAwareBeanPostProcessorAdapter {

public MyInstantiationAwareBeanPostProcessor() {
super();
System.out.println("这是InstantiationAwareBeanPostProcessorAdapter实现类构造器!!");
}

// 接口方法、实例化Bean之前调用
@Override
public Object postProcessBeforeInstantiation(Class beanClass, String beanName) throws BeansException {
System.out.println("InstantiationAwareBeanPostProcessor调用postProcessBeforeInstantiation方法");
return null;
}

//实例化后置方法调用:return false时,不再走spring的逻辑
@Override
public boolean postProcessAfterInstantiation(Object o, String s) throws BeansException {
System.out.println(":============="+o +"---------" + s);
System.out.println("InstantiationAwareBeanPostProcessor调用postProcessAfterInstantiation方法");
return true;
}

// 接口方法、设置某个属性时调用
@Override
public PropertyValues postProcessPropertyValues(PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException {
System.out.println("InstantiationAwareBeanPostProcessor调用postProcessPropertyValues方法");
return pvs;
}

//初始化前置方法调用
// @Override
// public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
// System.out.println("InstantiationAwareBeanPostProcessor调用postProcessBeforeInitialization方法对属性2进行更改");
// return bean;
// }
//
// // 接口方法、初始化Bean之后调用
// @Override
// public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
// System.out.println("InstantiationAwareBeanPostProcessor调用postProcessAfterInitialization方法对属性2进行更改");
// return bean;
// }
}

实现MyInstantiationAwareBeanPostProcessor,只覆写postProcessPropertyValues、postProcessBeforeInstantiation、postProcessAfterInstantiation三个接口。它也实现了BeanPostProcessor接口,在上文我们已经覆写postProcessBeforeInitialization、postProcessAfterInitialization方法。此处就不用再次覆写。---可以覆写,只不过会先执行BeanPostProcessor的实现类,然后再依次执行。

3.4 spring-config.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

<!--IoC的注解扫描-->
<!-- <context:component-scan base-package="com.xxx.beancycle.instant"></context:component-scan>-->

<bean id="beanPostProcessor" class=" com.xxx.beancycle.instant.MyBeanPostProcessor"></bean>

<bean id="instantiationAwareBeanPostProcessor" class=" com.xxx.beancycle.instant.MyInstantiationAwareBeanPostProcessor"></bean>

<bean id="person" class=" com.xxx.beancycle.instant.Person" init-method="myInit" destroy-method="myDestory">
<property name="name" value="张三"></property>
<property name="address" value="广州"></property>
<property name="phone" value="15900"></property>
</bean>

</beans>

通过setter注入的方式将上述bean对象注入到ioc容器中。

3.5 Test

1
2
3
4
5
6
7
8
9
@Test
public void testBean() {
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:com/xxx/beancycle/spring-config.xml");
System.out.println("容器初始化成功!!!");
System.out.println("现在开始关闭容器!!!");
Person bean = applicationContext.getBean("person", Person.class);
System.out.println("-----------"+bean);
applicationContext.close();
}

控制台打印如下:

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
17:20:52,762  INFO XmlBeanDefinitionReader:317 - Loading XML bean definitions from class path resource [com/xxx/beancycle/spring-config.xml]
这是BeanPostProcessor实现类构造器!!
这是InstantiationAwareBeanPostProcessorAdapter实现类构造器!!
InstantiationAwareBeanPostProcessor调用postProcessBeforeInstantiation方法
【构造器】调用Person的构造器实例化
:=============Person [address=null, name=null, phone=0]---------person
InstantiationAwareBeanPostProcessor调用postProcessAfterInstantiation方法
InstantiationAwareBeanPostProcessor调用postProcessPropertyValues方法
【注入属性】注入属性name:张三
【注入属性】注入属性address:广州
【注入属性】注入属性phone:15900
BeanPostProcessor接口方法postProcessBeforeInitialization对属性1进行更改!
==================Person [address=广州, name=张三, phone=15900]
【InitializingBean接口】调用InitializingBean.afterPropertiesSet()
【init-method】调用<bean>的init-method属性指定的初始化方法
BeanPostProcessor接口方法postProcessAfterInitialization对属性1进行更改!
容器初始化成功!!!
现在开始关闭容器!!!
-----------Person [address=广州, name=yangxin, phone=177]
17:20:52,892 INFO ClassPathXmlApplicationContext:984 - Closing org.springframework.context.support.ClassPathXmlApplicationContext@3ac3fd8b: startup date [Fri Mar 03 17:20:52 CST 2023]; root of context hierarchy
【DiposibleBean接口】调用DiposibleBean.destory()
【destroy-method】调用<bean>的destroy-method属性指定的初始化方法

Process finished with exit code 0

4.详解日志

4.1 实例化

对应下列日志:

1
2
3
4
5
6
7
这是BeanPostProcessor实现类构造器!!
这是InstantiationAwareBeanPostProcessorAdapter实现类构造器!!
InstantiationAwareBeanPostProcessor调用postProcessBeforeInstantiation方法
【构造器】调用Person的构造器实例化
:=============Person [address=null, name=null, phone=0]---------person
InstantiationAwareBeanPostProcessor调用postProcessAfterInstantiation方法
InstantiationAwareBeanPostProcessor调用postProcessPropertyValues方法

首先,spring会实例化MyBeanPostProcessor、MyInstantiationAwareBeanPostProcessor这些实现或者继承spring的类。然后再实例化我们定义的"bean",此处实例化Person类时,会优先执行InstantiationAwareBeanPostProcessor的postProcessBeforeInstantiation方法,也就是实例化前置方法。改方法允许我们在实例化对象的时候,可以对bean进行前置处理。然后通过反射实例化对象,

实例化完成之后会调用postProcessAfterInstantiation方法,该方法返回布尔值,如果返回false则不执行postProcessPropertyValues方法,也就是不会进行属性修改。

剩余的初始化方法会执行,也就是BeanPostProcessor的postProcessBeforeInitialization与postProcessAfterInitialization方法会执行。如果在这些方法里对bean都没有进行任何处理,则该bean的所有属性值均为默认值。

如下是返回false的日志:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
这是InstantiationAwareBeanPostProcessorAdapter实现类构造器!!
InstantiationAwareBeanPostProcessor调用postProcessBeforeInstantiation方法
【构造器】调用Person的构造器实例化
:=============Person [address=null, name=null, phone=0]---------person
InstantiationAwareBeanPostProcessor调用postProcessAfterInstantiation方法
InstantiationAwareBeanPostProcessor调用postProcessBeforeInitialization方法对属性2进行更改
==================Person [address=null, name=null, phone=0]
【InitializingBean接口】调用InitializingBean.afterPropertiesSet()
【init-method】调用<bean>的init-method属性指定的初始化方法
InstantiationAwareBeanPostProcessor调用postProcessAfterInitialization方法对属性2进行更改
容器初始化成功!!!
现在开始关闭容器!!!
-----------Person [address=null, name=null, phone=0]
17:33:33,215 INFO ClassPathXmlApplicationContext:984 - Closing org.springframework.context.support.ClassPathXmlApplicationContext@3ac3fd8b: startup date [Fri Mar 03 17:33:33 CST 2023]; root of context hierarchy
【DiposibleBean接口】调用DiposibleBean.destory()
【destroy-method】调用<bean>的destroy-method属性指定的初始化方法

------->打印的Person对象的属性值为空。

4.2 初始化

对应下列日志:

1
2
3
4
5
6
7
8
【注入属性】注入属性name:张三
【注入属性】注入属性address:广州
【注入属性】注入属性phone:15900
BeanPostProcessor接口方法postProcessBeforeInitialization对属性1进行更改!
==================Person [address=广州, name=张三, phone=15900]
【InitializingBean接口】调用InitializingBean.afterPropertiesSet()
【init-method】调用<bean>的init-method属性指定的初始化方法
BeanPostProcessor接口方法postProcessAfterInitialization对属性1进行更改!

我们可以看到在xml里、配置了

1
2
3
4
5
<bean id="person" class=" com.xxx.beancycle.instant.Person" init-method="myInit" destroy-method="myDestory">
<property name="name" value="张三"></property>
<property name="address" value="广州"></property>
<property name="phone" value="15900"></property>
</bean>

通过postProcessPropertyValues方法给bean填充属性、填充的就是我们在xml配置的属性。

aware接口我们暂时不用管。

然后执行BeanPostProcessor的postProcessBeforeInitialization方法,对bean进行初始化前置操作处理。

然后执行初始化方式(上文没有执行@PostConstruct标注的方法是因为我没有让spring扫描Persond对象。因此注解没有生效)

初始化方法优先级:

@PostConstruct--->InitializingBean.afterPropertiesSet()--->xml配置的Init-method

4.3 销毁

对应下列日志:

1
2
【DiposibleBean接口】调用DiposibleBean.destory()
【destroy-method】调用<bean>的destroy-method属性指定的初始化方法

销毁方法优先级:

@PreDestroy--->DiposibleBean.destory()--->xml配置的destroy-method

5.BeanFactoryPostProcessor

  • BeanPostProcessor
  • InstantiationAwareBeanPostProcessor

这两兄弟可能是Spring扩展中最重要的两个接口!InstantiationAwareBeanPostProcessor作用于实例化阶段的前后,BeanPostProcessor作用于初始化阶段的前后。

说到BeanPostProcessor,不得不提一下BeanFactoryPostProcessor,BeanFactoryPostProcessor和BeanPostProcessor,这两个接口,都是Spring初始化bean时对外暴露的扩展点。两个接口名称看起来很相似,但作用及使用场景却不同。

1
2
3
4
5
6
7
8
9
10
11
12
13
public interface BeanFactoryPostProcessor {

/**
* Modify the application context's internal bean factory after its standard
* initialization. All bean definitions will have been loaded, but no beans
* will have been instantiated yet. This allows for overriding or adding
* properties even to eager-initializing beans.
* @param beanFactory the bean factory used by the application context
* @throws org.springframework.beans.BeansException in case of errors
*/
void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;

}

现在我们新写一个类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {

public MyBeanFactoryPostProcessor() {
super();
System.out.println("这是BeanFactoryPostProcessor实现类构造器!!");
}

@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory arg0) throws BeansException {
System.out.println("BeanFactoryPostProcessor调用postProcessBeanFactory方法");
BeanDefinition bd = arg0.getBeanDefinition("person");
System.out.println("-=-=-=-=-=-="+bd.getPropertyValues());
System.out.println("-=-=-=-=-=-="+bd.getPropertyValues().get("address"));
System.out.println("-=-=-=-=-=-="+bd.getPropertyValues().get("name"));
System.out.println("-=-=-=-=-=-="+bd.getPropertyValues().get("phone"));
System.out.println("----------:操作bean的定义");
bd.getPropertyValues().addPropertyValue("phone", "110");
}

}

并且通过xml注入:

1
<bean id="beanFactoryPostProcessor" class=" com.xxx.beancycle.instant.MyBeanFactoryPostProcessor"></bean>

再运行测试类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
这是BeanFactoryPostProcessor实现类构造器!!
BeanFactoryPostProcessor调用postProcessBeanFactory方法
-=-=-=-=-=-=PropertyValues: length=3; bean property 'name'; bean property 'address'; bean property 'phone'
-=-=-=-=-=-=TypedStringValue: value [广州], target type [null]
-=-=-=-=-=-=TypedStringValue: value [张三], target type [null]
-=-=-=-=-=-=TypedStringValue: value [15900], target type [null]
----------:操作bean的定义
这是InstantiationAwareBeanPostProcessorAdapter实现类构造器!!
InstantiationAwareBeanPostProcessor调用postProcessBeforeInstantiation方法
【构造器】调用Person的构造器实例化
:=============Person [address=null, name=null, phone=0]---------person
InstantiationAwareBeanPostProcessor调用postProcessAfterInstantiation方法
InstantiationAwareBeanPostProcessor调用postProcessPropertyValues方法
【注入属性】注入属性name:张三
【注入属性】注入属性address:广州
【注入属性】注入属性phone:110
... ...

我们会发现我们在xml里定义的参数已经被改变了。以前的 【注入属性】注入属性phone:15900变为【注入属性】注入属性phone:110

实现该接口,可以在spring的bean创建之前,修改bean的定义属性。也就是说,Spring允许BeanFactoryPostProcessor在容器实例化任何其它bean之前读取配置元数据,并可以根据需要进行修改,例如可以把bean的scope从singleton改为prototype,也可以把property的值给修改掉。可以同时配置多个BeanFactoryPostProcessor,并通过设置'order'属性来控制各个BeanFactoryPostProcessor的执行次序。

6.Aware接口

为了更好的理解生命周期,我们前面暂时没有解释生命周期图中的第六步,也就是Aware接口,在此处我们来讲一下Aware接口。我们看一下spring对aware接口的解释:

A marker superinterface indicating that a bean is eligible to be notified by the Spring container of a particular framework object through a callback-style method. The actual method signature is determined by individual subinterfaces but should typically consist of just one void-returning method that accepts a single argument. Note that merely implementing Aware provides no default functionality. Rather, processing must be done explicitly, for example in a BeanPostProcessor. Refer to ApplicationContextAwareProcessor for an example of processing specific *Aware interface callbacks.

含义:

一个标记超接口,指示bean有资格通过回调样式方法被Spring容器通知特定框架对象。实际的方法签名由各个子接口确定,但通常只应由一个接受单个参数的返回空值的方法组成。

注意,仅实现Aware不提供默认功能。相反,处理必须显式完成,例如在BeanPostProcessor中。有关处理特定*Aware接口回调的示例,请参阅ApplicationContextAwareProcessor。

代码:

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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
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;
import org.springframework.context.*;
import org.springframework.context.annotation.ImportAware;
import org.springframework.context.weaving.LoadTimeWeaverAware;
import org.springframework.core.env.Environment;
import org.springframework.core.io.ResourceLoader;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.instrument.classloading.LoadTimeWeaver;
import org.springframework.jmx.export.notification.NotificationPublisher;
import org.springframework.jmx.export.notification.NotificationPublisherAware;
import org.springframework.stereotype.Component;
import org.springframework.util.StringValueResolver;
import org.springframework.web.context.ServletConfigAware;
import org.springframework.web.context.ServletContextAware;

import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;

@Component
public class AllAwareInterface implements BeanNameAware, BeanClassLoaderAware,
BeanFactoryAware, EnvironmentAware, EmbeddedValueResolverAware,
ResourceLoaderAware, ApplicationEventPublisherAware, MessageSourceAware,
ApplicationContextAware, ServletContextAware, LoadTimeWeaverAware, ImportAware ,
NotificationPublisherAware, ServletConfigAware, ApplicationStartupAware {

@Override
public void setBeanName(String name) {
// BeanNameAware作用:让Bean对Name有知觉
//这个方法只是简单的返回我们当前的beanName,听官方的意思是这个接口更多的使用在spring的框架代码中,实际开发环境应该不建议使用
System.out.println("1 我是 BeanNameAware 的 setBeanName 方法 ---参数:name,内容:"+ name);
}
@Override
public void setBeanClassLoader(ClassLoader classLoader) {
System.out.println("2 我是 BeanClassLoaderAware 的 setBeanClassLoader 方法");
}
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
// 注意: 如果使用 @Configuration 注解的话,setBeanFactory方法会执行2次,
System.out.println("3 我是 BeanFactoryAware 的 setBeanFactory 方法");
}
@Override
public void setEnvironment(Environment environment) {
System.out.println("4 我是 EnvironmentAware 的 setEnvironment 方法");
}
@Override
public void setEmbeddedValueResolver(StringValueResolver stringValueResolver) {
System.out.println("5 我是 EmbeddedValueResolverAware 的 setEmbeddedValueResolver 方法");
}
@Override
public void setResourceLoader(ResourceLoader resourceLoader) {
System.out.println("6 我是 ResourceLoaderAware 的 setResourceLoader 方法");
}
@Override
public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
System.out.println("7 我是 ApplicationEventPublisherAware 的 setApplicationEventPublisher 方法");
}
@Override
public void setMessageSource(MessageSource messageSource) {
System.out.println("8 我是 MessageSourceAware 的 setMessageSource 方法");
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
//实现ApplicationContextAware接口的类,都可以取得applicationContext
System.out.println("9 我是 ApplicationContextAware 的 setApplicationContext 方法");
}
@Override
public void setServletContext(ServletContext servletContext) {
//实现ServletContextAware接口的类,都可以取得ServletContext
System.out.println("10 我是 ServletContextAware 的 setServletContext 方法");
}
@Override
public void setLoadTimeWeaver(LoadTimeWeaver loadTimeWeaver) {
//LoadTimeWeaver 简称LTW,LTW是AOP的一种实现方式,此方法是为了获取Aop织入的对象,使用的织入方式是:类加载期织入,
// 一般的aop都是运行期织入,就是在运行的时候才进行织入切面方法,但是LTW是在类加载前就被织入了,也就是class文件在jvm加载之前进行织入切面方法
// 只有在使用 @EnableLoadTimeWeaving 或者存在 LoadTimeWeaver 实现的 Bean 时才会调用,顺序也很靠后
System.out.println("11 我是 LoadTimeWeaverAware 的 setLoadTimeWeaver 方法");
}
@Override
public void setImportMetadata(AnnotationMetadata annotationMetadata) {
//只有被其他配置类 @Import(XX.class) 时才会调用,这个调用对 XX.class 中的所有 @Bean 来说顺序是第 1 的。
System.out.println("12 我是 ImportAware 的 setImportMetadata 方法");
}

@Override
public void setNotificationPublisher(NotificationPublisher notificationPublisher) {
System.out.println("13 我是 NotificationPublisherAware 的 setNotificationPublisher 方法");
}

@Override
public void setServletConfig(ServletConfig servletConfig) {
//实现ServletContextAware接口的类,都可以取得ServletContext
System.out.println("14 我是 ServletConfigAware 的 setServletConfig 方法");
}

@Override
public void setApplicationStartup(ApplicationStartup applicationStartup) {
//容器启动成功后,通过ApplicationStartup进行相应处理。
System.out.println("15 我是 ApplicationStartupAware 的 setApplicationStartup 方法");
}
}

spring中所有的aware接口:

ApplicationEventPublisherAware, ApplicationStartupAware, BeanClassLoaderAware, BeanFactoryAware, BeanNameAware, EmbeddedValueResolverAware, EnvironmentAware, ImportAware, LoadTimeWeaverAware, MessageSourceAware, NotificationPublisherAware, ResourceLoaderAware, SchedulerContextAware, ServletConfigAware, ServletContextAware

本着最简单的原则,本文不会讲aware接口全部讲解,只讲最常用的aware接口。

6.1 ApplicationContextAware

该接口是最常用的一个注解,通过实现ApplicationContextAware接口,我们能够得到applicationContext,因此我们可以再spring容器启动的试试,对容器进行处理。

6.2 ApplicationStartupAware

通过实现ApplicationStartupAware接口,可以在容器启动成功后,通过ApplicationStartup进行相应处理。

6.3 BeanFactoryAware

让Bean获取配置他们的BeanFactory的引用。

6.4 BeanNameAware

调用BeanNameAware接口的实现类中的setBeanName方法,获取容器中 Bean 的名称,

6.5 EnvironmentAware

实现了EnvironmentAware接口重写setEnvironment方法后,在工程启动时可以获得application.properties 、xml、yml 的配置文件配置的属性值。

7. 总结

spring生命周期

总结:

spring的生命周期分为实例化属性赋值初始化销毁

  • 如果 BeanFactoryPostProcessor 和 Bean 关联, 则调用postProcessBeanFactory方法.(即首先尝试从Bean工厂中获取Bean)
  • 如果 InstantiationAwareBeanPostProcessor 和 Bean 关联,则调用postProcessBeforeInstantiation方法
  • 根据配置情况调用 Bean 构造方法实例化 Bean
  • 如果 InstantiationAwareBeanPostProcessor 和 Bean 关联,则调用postProcessAfterInstantiation方法和postProcessPropertyValues方法(前几个版本叫postProcessProperty)
  • 调用setter方法完成 Bean 中属性注入
  • 调用xxxAware接口
    • 第一类Aware接口
      • 如果 Bean 实现了 BeanNameAware 接口,则 Spring 调用 Bean 的 setBeanName() 方法传入当前 Bean 的 id 值。
      • 如果 Bean 实现了 BeanClassLoaderAware 接口,则 Spring 调用 setBeanClassLoader() 方法传入classLoader的引用。
      • 如果 Bean 实现了 BeanFactoryAware 接口,则 Spring 调用 setBeanFactory() 方法传入当前工厂实例的引用。
    • 第二类Aware接口
      • 如果 Bean 实现了 EnvironmentAware 接口,则 Spring 调用 setEnvironment() 方法传入当前 Environment 实例的引用。
      • 如果 Bean 实现了 EmbeddedValueResolverAware 接口,则 Spring 调用 setEmbeddedValueResolver() 方法传入当前 StringValueResolver 实例的引用。
      • 如果 Bean 实现了 ApplicationContextAware 接口,则 Spring 调用 setApplicationContext() 方法传入当前 ApplicationContext 实例的引用。
      • ... ...

  • 如果 BeanPostProcessor 和 Bean 关联,则 Spring 将调用该接口的预初始化方法 postProcessBeforeInitialzation()对 Bean 进行加工操作,此处非常重要,Spring 的 AOP 就是利用它实现的。
  • Bean初始化前置方法
    • 如果 Bean有执行@PostConstruct注解的方法,则调用该初始化方法。
    • 如果 Bean 实现了InitializingBean 接口,则 调用 afterPropertiesSet() 方法。
    • 如果在配置文件中通过 init-method 属性指定了初始化方法,则调用该初始化方法。
  • 如果 BeanPostProcessor 和 Bean 关联,则 Spring 将调用该接口的初始化方法 postProcessAfterInitialization()。此时,Bean 已经可以被应用系统使用了。
  • 如果在 <bean> 中指定了该 Bean 的作用范围为 scope="singleton",则将该 Bean 放入 Spring IoC 的缓存池中,将触发 Spring 对该 Bean 的生命周期管理;如果在 <bean> 中指定了该 Bean 的作用范围为 scope="prototype",则将该 Bean 交给调用者,调用者管理该 Bean 的生命周期,Spring 不再管理该 Bean。

  • Bean销毁前置方法
    • 如果 Bean有执行@PreDestroy注解的方法,则调用该初始化方法。
    • 如果 Bean 实现了 DisposableBean 接口,则 Spring 会调用 destory() 方法将 Spring 中的 Bean 销毁
    • 如果在配置文件中通过 destory-method 属性指定了 Bean 的销毁方法,则 Spring 将调用该方法对 Bean 进行销毁。

Bean的完整生命周期经历了各种方法调用,这些方法可以划分为以下几类:(结合上图,需要有如下顶层思维)

  • Bean自身的方法: 这个包括了Bean本身调用的方法和通过配置文件中<bean>的init-method和destroy-method指定的方法
  • Bean级生命周期接口方法: 这个包括了BeanNameAware、BeanFactoryAware、ApplicationContextAware;当然也包括InitializingBean和DiposableBean这些接口的方法(可以被@PostConstruct和@PreDestroy注解替代)
  • 容器级生命周期接口方法: 这个包括了InstantiationAwareBeanPostProcessor 和 BeanPostProcessor 这两个接口实现,一般称它们的实现类为“后处理器”。
  • 工厂后处理器接口方法: 这个包括了AspectJWeavingEnabler, ConfigurationClassPostProcessor, CustomAutowireConfigurer等等非常有用的工厂后处理器接口的方法。工厂后处理器也是容器级的。在应用上下文装配配置文件之后立即调用。

8.Read more

:lollipop::https://blog.csdn.net/caihaijiang/article/details/35552859

:lollipop::https://www.cnblogs.com/zrtqsk/p/3735273.html

:lollipop::https://pdai.tech/md/spring/spring-x-framework-ioc-source-3.html


博客说明

文章所涉及的资料来自互联网整理和个人总结,意在于个人学习和经验汇总,不用于任何的商业用途。如有侵权,请联系本人删除。谢谢!


Spring Bean生命周期
https://nanchengjiumeng123.top/2022/05/20/framework/spring/Spring IoC/2022-05-20_Spring Bean生命周期/
作者
Yang Xin
发布于
2022年5月20日
许可协议