bean的生命周期是一道很常见的面试题, 用代码具象化一下,很容易就理解了.
@Slf4j
@Component
public class LifeCycleBean {
public LifeCycleBean(){
log.info("构造方法,实例化");
}
@Autowired
public void autowired(@Value("${spring.application.name}") String name){
log.info("属性注入{}",name);
}
//注解直译: 构造函数 后
@PostConstruct
public void init(){
log.debug("初始化");
}
//注解直译: 销毁 前
public void destroy(){
log.debug("销毁");
}
}
基本就是按照这几个步骤,
1.实例化,先调用构造方法创建对象,
2.注入属性
3. 初始化
4. 销毁
测试可以在Application类中 run后给它close关掉,来模拟销毁.
/**
* 启动类
*
* @author linnine09
* @since 2022-04-10,v1.0.0
*/
@SpringBootApplication
public class A03Application {
public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException, IOException {
ConfigurableApplicationContext context = SpringApplication.run(A03Application.class);
context.close();
}
}
大概的日志是这样的
最后是销毁
前面在讲BeanFactory的时候就有讲到bean的后处理器, 通过这些后处理器还可以在bean的生命周期中做一些增加的骚操作.
回忆一下, PostProcessor 拆开来就是: Post后置 Processor处理器 所以就是后置处理器
主要是这两个接口InstantiationAwareBeanPostProcessor, DestructionAwareBeanPostProcessor
实例化后置处理器,和销毁后置处理器
@Slf4j
@Component
public class MyBeanPostProcessor implements InstantiationAwareBeanPostProcessor, DestructionAwareBeanPostProcessor {
@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
if (beanName.equals("lifeCycleBean"))
log.debug("<<<<<<<<<<< 实例化前执行,如@PreDestroy");
// 返回null保持原有对象不变,返回不为null,会替换掉原有对象
return null;
//return InstantiationAwareBeanPostProcessor.super.postProcessBeforeInstantiation(beanClass, beanName);
}
@Override
public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
if (beanName.equals("lifeCycleBean")) {
log.debug("<<<<<<<<<<< 实例化后执行,这里如果返回 false 会跳过依赖注入阶段");
// return false;
}
return true;
//return InstantiationAwareBeanPostProcessor.super.postProcessAfterInstantiation(bean, beanName);
}
@Override
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException {
if (beanName.equals("lifeCycleBean"))
log.debug("<<<<<<<<<<< 依赖注入阶段执行,如@Autowired、@Value、@Resource");
return pvs;
//return InstantiationAwareBeanPostProcessor.super.postProcessProperties(pvs, bean, beanName);
}
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if(beanName.equals("lifeCycleBean"))
log.debug("<<<<<<<<<<< 初始化之前执行,这里返回的对象会替换掉原本的bean,如 @PostConstruct、@ConfigurationProperties");
return bean;
//return InstantiationAwareBeanPostProcessor.super.postProcessBeforeInitialization(bean, beanName);
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if(beanName.equals("lifeCycleBean"))
log.debug("<<<<<<<<<<< 初始化之后执行,这里返回的对象会替换掉原本的bean,如 代理增强");
return bean;
//return InstantiationAwareBeanPostProcessor.super.postProcessAfterInitialization(bean, beanName);
}
@Override
public void postProcessBeforeDestruction(Object o, String beanName) throws BeansException {
if(beanName.equals("lifeCycleBean"))
log.debug("<<<<<<<<<<<销毁之前执行");
}
}
比如说 需要对一些类做一些统一的处理操作,就可以在这里实现,这里是对类名进行判断, 如果没有判断 每个类执行这些步骤时都会打印.
补充一个模板方法的设计模式
/**
* 模板方法
*/
public class TestMethodTemplate {
public static void main(String[] args) {
//原本的后处理器工厂里面没有处理器
MyBeanFactory myBeanFactory = new MyBeanFactory();
//在外部实现起方法后 加入到处理器工厂
myBeanFactory.addProcesses(bean -> System.out.println("解析@Autowired"));
myBeanFactory.addProcesses(bean -> System.out.println("解析@Resource"));
//在内部遍历调用处理器来进行实现,方便对方法进行外部扩展
Object bean = myBeanFactory.getBean();
}
static class MyBeanFactory{
public Object getBean(){
Object bean = new Object();
System.out.println("构造");
System.out.println("依赖注入");
//一般的我们后续要补充一些操作,比如添加一些后置处理器,需要改变此处的代码
//但是每次都来改造这个方法,会使这个代码变得臃肿 也就是扩展性差
//所以我们可以定义一个方法工厂,将一些方法的实现注入进后,在此处拿来使用
processes.forEach(process-> process.inject(bean));
System.out.println("初始化");
return bean;
}
//一般有两种结构的工厂 一种是map型 一种是list型
//map 主要用于1对1 传不同的类进来,根据需求去调用处理类
//list 主要用于1对多 不管传什么类进来, 我都要走一遍全部的处理
public static List<BeanPostProcess> processes=new ArrayList<>();
/**
* 这里提供一个口子 供外部传入实现类
* @param beanPostProcess
*/
public void addProcesses(BeanPostProcess beanPostProcess){
processes.add(beanPostProcess);
}
}
//后置处理器接口 把方法抽象化 把需求定下 外部自行实现
interface BeanPostProcess{
void inject(Object bean);
}
}