Skip to content

Commit 9edd292

Browse files
authored
Merge pull request crossoverJie#21 from crossoverJie/dev
Spring bean lifecycle
2 parents 0a8b885 + 438b610 commit 9edd292

14 files changed

+491
-0
lines changed

MD/spring/spring-bean-lifecycle.md

Lines changed: 180 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,180 @@
1+
## Spring Bean 生命周期
2+
3+
4+
5+
Spring Bean 的生命周期在整个 Spring 中占有很重要的位置,掌握这些可以加深对 Spring 的理解。
6+
7+
首先看下生命周期图:
8+
9+
![](https://ws3.sinaimg.cn/large/006tNc79gy1fpjsamy6uoj30nt0cqq4i.jpg)
10+
11+
再谈生命周期之前有一点需要先明确:
12+
13+
> Spring 只帮我们管理单例模式 Bean 的**完整**生命周期,对于 prototype 的 bean ,Spring 在创建好交给使用者之后则不会再管理后续的生命周期。
14+
15+
16+
### 注解方式
17+
18+
在 bean 初始化时会经历几个阶段,首先可以使用注解 `@PostConstruct`, `@PreDestroy` 来在 bean 的创建和销毁阶段进行调用:
19+
20+
```java
21+
@Component
22+
public class AnnotationBean {
23+
private final static Logger LOGGER = LoggerFactory.getLogger(AnnotationBean.class);
24+
25+
@PostConstruct
26+
public void start(){
27+
LOGGER.info("AnnotationBean start");
28+
}
29+
30+
@PreDestroy
31+
public void destroy(){
32+
LOGGER.info("AnnotationBean destroy");
33+
}
34+
}
35+
```
36+
37+
### InitializingBean, DisposableBean 接口
38+
39+
还可以实现 `InitializingBean,DisposableBean` 这两个接口,也是在初始化以及销毁阶段调用:
40+
41+
```java
42+
@Service
43+
public class SpringLifeCycleService implements InitializingBean,DisposableBean{
44+
private final static Logger LOGGER = LoggerFactory.getLogger(SpringLifeCycleService.class);
45+
@Override
46+
public void afterPropertiesSet() throws Exception {
47+
LOGGER.info("SpringLifeCycleService start");
48+
}
49+
50+
@Override
51+
public void destroy() throws Exception {
52+
LOGGER.info("SpringLifeCycleService destroy");
53+
}
54+
}
55+
```
56+
57+
### 自定义初始化和销毁方法
58+
59+
也可以自定义方法用于在初始化、销毁阶段调用:
60+
61+
```java
62+
@Configuration
63+
public class LifeCycleConfig {
64+
65+
66+
@Bean(initMethod = "start", destroyMethod = "destroy")
67+
public SpringLifeCycle create(){
68+
SpringLifeCycle springLifeCycle = new SpringLifeCycle() ;
69+
70+
return springLifeCycle ;
71+
}
72+
}
73+
74+
public class SpringLifeCycle{
75+
76+
private final static Logger LOGGER = LoggerFactory.getLogger(SpringLifeCycle.class);
77+
public void start(){
78+
LOGGER.info("SpringLifeCycle start");
79+
}
80+
81+
82+
public void destroy(){
83+
LOGGER.info("SpringLifeCycle destroy");
84+
}
85+
}
86+
```
87+
88+
以上是在 SpringBoot 中可以这样配置,如果是原始的基于 XML 也是可以使用:
89+
90+
```xml
91+
<bean class="com.crossoverjie.spring.SpringLifeCycle" init-method="start" destroy-method="destroy">
92+
</bean>
93+
```
94+
95+
来达到同样的效果。
96+
97+
### 实现 *Aware 接口
98+
99+
`*Aware` 接口可以用于在初始化 bean 时获得 Spring 中的一些对象,如获取 `Spring 上下文`等。
100+
101+
```java
102+
@Component
103+
public class SpringLifeCycleAware implements ApplicationContextAware {
104+
private final static Logger LOGGER = LoggerFactory.getLogger(SpringLifeCycleAware.class);
105+
106+
private ApplicationContext applicationContext ;
107+
108+
@Override
109+
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
110+
this.applicationContext = applicationContext ;
111+
LOGGER.info("SpringLifeCycleAware start");
112+
}
113+
}
114+
```
115+
116+
这样在 `springLifeCycleAware` 这个 bean 初始化会就会调用 `setApplicationContext` 方法,并可以获得 `applicationContext` 对象。
117+
118+
### BeanPostProcessor 增强处理器
119+
120+
实现 BeanPostProcessor 接口,Spring 中所有 bean 在做初始化时都会调用该接口中的两个方法,可以用于对一些特殊的 bean 进行处理:
121+
122+
```java
123+
@Component
124+
public class SpringLifeCycleProcessor implements BeanPostProcessor {
125+
private final static Logger LOGGER = LoggerFactory.getLogger(SpringLifeCycleProcessor.class);
126+
127+
/**
128+
* 预初始化 初始化之前调用
129+
* @param bean
130+
* @param beanName
131+
* @return
132+
* @throws BeansException
133+
*/
134+
@Override
135+
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
136+
if ("annotationBean".equals(beanName)){
137+
LOGGER.info("SpringLifeCycleProcessor start beanName={}",beanName);
138+
}
139+
return bean;
140+
}
141+
142+
/**
143+
* 后初始化 bean 初始化完成调用
144+
* @param bean
145+
* @param beanName
146+
* @return
147+
* @throws BeansException
148+
*/
149+
@Override
150+
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
151+
if ("annotationBean".equals(beanName)){
152+
LOGGER.info("SpringLifeCycleProcessor end beanName={}",beanName);
153+
}
154+
return bean;
155+
}
156+
}
157+
```
158+
159+
执行之后观察结果:
160+
161+
```
162+
018-03-21 00:40:24.856 [restartedMain] INFO c.c.s.p.SpringLifeCycleProcessor - SpringLifeCycleProcessor start beanName=annotationBean
163+
2018-03-21 00:40:24.860 [restartedMain] INFO c.c.spring.annotation.AnnotationBean - AnnotationBean start
164+
2018-03-21 00:40:24.861 [restartedMain] INFO c.c.s.p.SpringLifeCycleProcessor - SpringLifeCycleProcessor end beanName=annotationBean
165+
2018-03-21 00:40:24.864 [restartedMain] INFO c.c.s.aware.SpringLifeCycleAware - SpringLifeCycleAware start
166+
2018-03-21 00:40:24.867 [restartedMain] INFO c.c.s.service.SpringLifeCycleService - SpringLifeCycleService start
167+
2018-03-21 00:40:24.887 [restartedMain] INFO c.c.spring.SpringLifeCycle - SpringLifeCycle start
168+
2018-03-21 00:40:25.062 [restartedMain] INFO o.s.b.d.a.OptionalLiveReloadServer - LiveReload server is running on port 35729
169+
2018-03-21 00:40:25.122 [restartedMain] INFO o.s.j.e.a.AnnotationMBeanExporter - Registering beans for JMX exposure on startup
170+
2018-03-21 00:40:25.140 [restartedMain] INFO com.crossoverjie.Application - Started Application in 2.309 seconds (JVM running for 3.681)
171+
2018-03-21 00:40:25.143 [restartedMain] INFO com.crossoverjie.Application - start ok!
172+
2018-03-21 00:40:25.153 [Thread-8] INFO o.s.c.a.AnnotationConfigApplicationContext - Closing org.springframework.context.annotation.AnnotationConfigApplicationContext@3913adad: startup date [Wed Mar 21 00:40:23 CST 2018]; root of context hierarchy
173+
2018-03-21 00:40:25.155 [Thread-8] INFO o.s.j.e.a.AnnotationMBeanExporter - Unregistering JMX-exposed beans on shutdown
174+
2018-03-21 00:40:25.156 [Thread-8] INFO c.c.spring.SpringLifeCycle - SpringLifeCycle destroy
175+
2018-03-21 00:40:25.156 [Thread-8] INFO c.c.s.service.SpringLifeCycleService - SpringLifeCycleService destroy
176+
2018-03-21 00:40:25.156 [Thread-8] INFO c.c.spring.annotation.AnnotationBean - AnnotationBean destroy
177+
```
178+
179+
直到 Spring 上下文销毁时则会调用自定义的销毁方法以及实现了 `DisposableBean``destroy()` 方法。
180+
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package com.crossoverjie.design.pattern.factorymethod;
2+
3+
/**
4+
* Function:
5+
*
6+
* @author crossoverJie
7+
* Date: 19/03/2018 14:29
8+
* @since JDK 1.8
9+
*/
10+
public abstract class Animal {
11+
12+
private String name ;
13+
14+
public String getName() {
15+
return name;
16+
}
17+
18+
public void setName(String name) {
19+
this.name = name;
20+
}
21+
22+
/**
23+
* 描述抽象方法
24+
*/
25+
protected abstract void desc() ;
26+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package com.crossoverjie.design.pattern.factorymethod;
2+
3+
/**
4+
* Function:工厂方法模式
5+
*
6+
* @author crossoverJie
7+
* Date: 19/03/2018 14:29
8+
* @since JDK 1.8
9+
*/
10+
public interface AnimalFactory {
11+
12+
Animal createAnimal() ;
13+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package com.crossoverjie.design.pattern.factorymethod;
2+
3+
/**
4+
* Function:
5+
*
6+
* @author crossoverJie
7+
* Date: 19/03/2018 14:33
8+
* @since JDK 1.8
9+
*/
10+
public class Cat extends Animal {
11+
@Override
12+
protected void desc() {
13+
System.out.println("Cat name is=" + this.getName());
14+
}
15+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package com.crossoverjie.design.pattern.factorymethod;
2+
3+
/**
4+
* Function:
5+
*
6+
* @author crossoverJie
7+
* Date: 19/03/2018 15:21
8+
* @since JDK 1.8
9+
*/
10+
public class CatFactory implements AnimalFactory {
11+
@Override
12+
public Animal createAnimal() {
13+
return new Cat();
14+
}
15+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package com.crossoverjie.design.pattern.factorymethod;
2+
3+
/**
4+
* Function:
5+
*
6+
* @author crossoverJie
7+
* Date: 19/03/2018 14:32
8+
* @since JDK 1.8
9+
*/
10+
public class Fish extends Animal {
11+
12+
13+
@Override
14+
protected void desc() {
15+
System.out.println("fish name is=" + this.getName());
16+
}
17+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package com.crossoverjie.design.pattern.factorymethod;
2+
3+
/**
4+
* Function:
5+
*
6+
* @author crossoverJie
7+
* Date: 19/03/2018 15:21
8+
* @since JDK 1.8
9+
*/
10+
public class FishFactory implements AnimalFactory {
11+
@Override
12+
public Animal createAnimal() {
13+
return new Fish() ;
14+
}
15+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package com.crossoverjie.design.pattern.factorymethod;
2+
3+
/**
4+
* Function:
5+
*
6+
* @author crossoverJie
7+
* Date: 19/03/2018 14:34
8+
* @since JDK 1.8
9+
*/
10+
public class Main {
11+
public static void main(String[] args) {
12+
AnimalFactory factory = new CatFactory() ;
13+
Animal animal = factory.createAnimal();
14+
animal.setName("猫咪");
15+
animal.desc();
16+
}
17+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
package com.crossoverjie.spring;
2+
3+
import com.crossoverjie.concurrent.Singleton;
4+
import org.springframework.context.annotation.Bean;
5+
import org.springframework.context.annotation.ComponentScan;
6+
import org.springframework.context.annotation.Configuration;
7+
8+
/**
9+
* Function:使用 initMethod 和 destroyMethod 的方式
10+
*
11+
* @author crossoverJie
12+
* Date: 19/03/2018 22:37
13+
* @since JDK 1.8
14+
*/
15+
@Configuration
16+
public class LifeCycleConfig {
17+
18+
19+
@Bean(initMethod = "start", destroyMethod = "destroy")
20+
public SpringLifeCycle create(){
21+
SpringLifeCycle springLifeCycle = new SpringLifeCycle() ;
22+
23+
return springLifeCycle ;
24+
}
25+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
package com.crossoverjie.spring;
2+
3+
import com.crossoverjie.Application;
4+
import org.slf4j.Logger;
5+
import org.slf4j.LoggerFactory;
6+
import org.springframework.beans.BeansException;
7+
import org.springframework.context.ApplicationContext;
8+
import org.springframework.context.ApplicationContextAware;
9+
10+
/**
11+
* Function:
12+
*
13+
* @author crossoverJie
14+
* Date: 20/03/2018 18:23
15+
* @since JDK 1.8
16+
*/
17+
public class SpringLifeCycle{
18+
19+
private final static Logger LOGGER = LoggerFactory.getLogger(SpringLifeCycle.class);
20+
public void start(){
21+
LOGGER.info("SpringLifeCycle start");
22+
}
23+
24+
25+
public void destroy(){
26+
LOGGER.info("SpringLifeCycle destroy");
27+
}
28+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package com.crossoverjie.spring.annotation;
2+
3+
import com.crossoverjie.spring.SpringLifeCycle;
4+
import org.slf4j.Logger;
5+
import org.slf4j.LoggerFactory;
6+
import org.springframework.stereotype.Component;
7+
8+
import javax.annotation.PostConstruct;
9+
import javax.annotation.PreDestroy;
10+
11+
/**
12+
* Function:用注解的方法
13+
*
14+
* @author crossoverJie
15+
* Date: 20/03/2018 18:46
16+
* @since JDK 1.8
17+
*/
18+
@Component
19+
public class AnnotationBean {
20+
private final static Logger LOGGER = LoggerFactory.getLogger(AnnotationBean.class);
21+
22+
@PostConstruct
23+
public void start(){
24+
LOGGER.info("AnnotationBean start");
25+
}
26+
27+
@PreDestroy
28+
public void destroy(){
29+
LOGGER.info("AnnotationBean destroy");
30+
}
31+
}

0 commit comments

Comments
 (0)