Bean的生命周期
- 一、生命周期演示
- 二、添加Bean后置处理器
简单的描述并测试Bean的生命周期(细节会在后续文章中单独讲解),并加入一些BeanPostPorcessor处理测试。
一、生命周期演示
准备一个普通的SpringBoot项目
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
/**
* 测试Bean的生命周期
*
* @Author linqibin
* @Date 2023/8/21 23:12
* @Email 1214219989@qq.com
*/
@SpringBootApplication
@Slf4j
public class LifeCycleApplication {
public static void main(String[] args) {
ConfigurableApplicationContext context = SpringApplication.run(LifeCycleApplication.class, args);
}
@Component("bean01")
static class Bean01 {
public Bean01() {
log.error("Bean实例化,构造函数被执行~~~~~~~~~");
}
@PostConstruct
public void init() {
log.error("Bean初始化阶段~~~~~~~~~~~~~~~");
}
@Autowired
private void autowired(@Value("${JAVA_HOME}" String javaHome) {
log.error("依赖注入阶段~~~~~~~~~~~~~~~~~{}", javaHome);
}
@PreDestroy
private void destroy() {
log.error("bean销毁阶段~~~~~~~~~~~~~~~~");
}
}
}
分别在内部类Bean01
的无参构造、初始化方法init()
、依赖注入、销毁方法。
@autowired
如果被加在方法上,并且方法的参数是一些普通的对象,Spring会从容器中注入这个对象,但我们的参数是String,肯定是无法注入的,我们只需要在参数前添加@Value("${}")
,并指定变量的名称,就可以冲系统变量或应用变量中找到并注入。
先跑一下,看下结果:
可以得出执行顺序是:
Bean实例化 → 依赖注入 → Bean初始化 → Bean销毁
二、添加Bean后置处理器
在刚才的LifeCycleApplication
中添加一个内部类,方法比较多,不过大部分都是见名知意,代码如下:
@Component
static class MyBeanPostProcessor implements InstantiationAwareBeanPostProcessor, DestructionAwareBeanPostProcessor {
@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
// SpringBoot中的应用程序比较多,因此我们只看自己定义的那个Bean01
if (beanName.equals("bean01")) {
log.error(">>>>>>>>>> BeforeInstantiation: 在实例化之前被执行~");
}
return null;
}
@Override
public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
if (beanName.equals("bean01")) {
log.error(">>>>>>>>>> AfterInstantiation: 在实例化之后被执行~");
}
return true;
}
@Override
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException {
if (beanName.equals("bean01")) {
log.error(">>>>>>>>>> postProcessProperties: 在依赖注入之前被执行~");
}
return pvs;
}
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if (beanName.equals("bean01")) {
log.error(">>>>>>>>>> BeforeInitialization: 在初始化之前被执行~");
}
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (beanName.equals("bean01")) {
log.error(">>>>>>>>>> AfterInitialization: 在初始化之后被执行~");
}
return bean;
}
@Override
public void postProcessBeforeDestruction(Object bean, String beanName) throws BeansException {
if (beanName.equals("bean01")) {
log.error(">>>>>>>>>> BeforeDestruction: 比Bean销毁方法先执行~");
}
}
}
重新运行:
可以看见在创建一个Bean的各个生命周期阶段前后,都可以做很多的扩展。
最后,我们再来看下各个扩展点的作用:
postProcessBeforeInstantiation
:该方法返回的对象,会替换原本的Bean。postProcessAfterInstantiation
:如果返回false,则会跳过依赖注入阶段。postProcessAfterInstantiation
:依赖注入阶段执行,如@Autowired
、@Value
、@Resource
。postProcessBeforeInitialization
:初始化之前执行,返回对象会替换掉原有的Bean。如@PostConstructor
、@ConfigurationProperties
- `postProcessAfterInitialization``:初始化方法之后执行,返回对象会替换原有的Bean,如代理增强。
postProcessBeforeDestruction
:销毁之前执行,如@PreDestroy