Spring生态目前发展很快,Spring、Spring Boot、Spring Cloud、Spring Data等等越来越丰富,并且迭代也很快。
最近在找工作,面试过程中经常有问到Spring的基础知识,其中一个知识点就是Spring中Bean的生命周期。
如果没有准备,突然问这道题有点答不上来。大概想的话就是先执行构造函数,执行一些接口方法(比如ContextAware、afterPropertiesSet),
然后执行@PostConstruct标记的方法,最后执行destroy方法(如果有的话)。
平常工作中:
@PostConstruct
有用到过,在类构造完成后用来执行一些自定义的初始化逻辑;
afterPropertiesSet
记得在Spring提供的类里经常有看到;
ApplicationContextAware
接口有在工具类用到,通过定义一个static变量和方法来获Spring的Context。
找到一张图:
写个Bean类来测试一下:
package com.cdfive.learning.spring;
import ch.qos.logback.classic.Level;
import ch.qos.logback.classic.LoggerContext;
import org.slf4j.LoggerFactory;
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.beans.factory.config.BeanPostProcessor;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
/**
* Test for Spring Bean lifecycle
*
* @author cdfive
* @date 2019-04-09
*/
@Component
public class BeanLifecycle implements BeanNameAware, BeanFactoryAware, ApplicationContextAware
, BeanPostProcessor, InitializingBean, DisposableBean {
private static int STEP = 0;
private String name;
private Integer age;
public static void main(String[] args) {
// Close the log
LoggerContext loggerContext= (LoggerContext) LoggerFactory.getILoggerFactory();
ch.qos.logback.classic.Logger logger=loggerContext.getLogger("root");
logger.setLevel(Level.OFF);
// Create a Spring ApplicationContext and start
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext("com.cdfive.learning.spring");
ctx.start();
// Close the ApplicationContext
ctx.close();
}
public BeanLifecycle() {
print("constructor");
}
@PostConstruct
public void postConstruct() {
print("@PostConstruct");
}
@PreDestroy
public void preDestroy() {
print("@PreDestroy");
}
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
print("BeanFactoryAware=>setBeanFactory");
}
@Override
public void setBeanName(String s) {
print("BeanNameAware=>setBeanName");
}
@Override
public void destroy() throws Exception {
print("DisposableBean=>destroy");
}
@Override
public void afterPropertiesSet() throws Exception {
print("InitializingBean=>afterPropertiesSet");
}
@Override
public Object postProcessBeforeInitialization(Object o, String s) throws BeansException {
print("BeanPostProcessor=>postProcessBeforeInitialization");
return null;
}
@Override
public Object postProcessAfterInitialization(Object o, String s) throws BeansException {
print("BeanPostProcessor=>postProcessAfterInitialization");
return null;
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
print("ApplicationContextAware=>setApplicationContext");
}
private static void print(String s) {
System.out.println((++STEP) + "." + s);
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
}
SpringBoot 2.0.5.RELEASE(即Spring 5.0.9.RELEASE)输出如下:
1.constructor
2.BeanNameAware=>setBeanName
3.BeanFactoryAware=>setBeanFactory
4.ApplicationContextAware=>setApplicationContext
5.@PostConstruct
6.InitializingBean=>afterPropertiesSet
7.BeanPostProcessor=>postProcessBeforeInitialization
8.BeanPostProcessor=>postProcessAfterInitialization
9.BeanPostProcessor=>postProcessBeforeInitialization
10.BeanPostProcessor=>postProcessAfterInitialization
11.@PreDestroy
12.DisposableBean=>destroy
可以看到,基本跟那张图一致。
不过有一点很奇怪的是BeanPostProcessor的postProcessBeforeInitialization、postProcessAfterInitialization执行了2次。
尝试把版本降低点,改为1.5.10.RELEASE(即Spring 4.3.14.RELEASE)输出如下:
1.constructor
2.BeanNameAware=>setBeanName
3.BeanFactoryAware=>setBeanFactory
4.ApplicationContextAware=>setApplicationContext
5.@PostConstruct
6.InitializingBean=>afterPropertiesSet
7.BeanPostProcessor=>postProcessBeforeInitialization
8.BeanPostProcessor=>postProcessBeforeInitialization
9.@PreDestroy
10.DisposableBean=>destroy
其中BeanPostProcessor的postProcessBeforeInitialization执行了2次,postProcessAfterInitialization没有执行。
关于BeanPostProcessor还有待研究,暂时没有找到这个问题的原因.
加深一下印象,基础知识确实应经常温习、总结。加油!