第三讲-Bean的生命周期和模板方法
第三讲 Bean的生命周期和模板方法
1. Spring 生命周期的各个阶段
首先准备好一个Spring容器:
@SpringBootApplication
public class A03Application {
public static void main(String[] args) {
ConfigurableApplicationContext context = SpringApplication.run(A03Application.class, args);
context.close();
}
}
准备一个Bean:
package com.cherry.chapter1.a03;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
@Component
public class LifeCycleBean {
private static final Logger log = LoggerFactory.getLogger(LifeCycleBean.class);
public LifeCycleBean(){
log.debug("构造方法被调用");
}
@Autowired
public void autowired(@Value("${JAVA_HOME}")String javaHome){
log.debug("依赖注入:{}",javaHome);
}
@PostConstruct
public void init(){
log.debug("初始化");
}
@PreDestroy
public void destroy(){
log.debug("销毁");
}
}
接下来我们启动程序,查看运行结果:
2024-07-21 11:11:50.641 DEBUG 17064 --- [ main] com.cherry.chapter1.a03.LifeCycleBean : 构造方法被调用
2024-07-21 11:11:50.644 DEBUG 17064 --- [ main] com.cherry.chapter1.a03.LifeCycleBean : 依赖注入:D:\development_tools\jdk17\jdk-17.0.10
2024-07-21 11:11:50.646 DEBUG 17064 --- [ main] com.cherry.chapter1.a03.LifeCycleBean : 初始化
2024-07-21 11:11:50.941 WARN 17064 --- [ main] o.s.b.a.f.FreeMarkerAutoConfiguration : Cannot find template location(s): [classpath:/templates/] (please add some templates, check your FreeMarker configuration, or set spring.freemarker.checkTemplateLocation=false)
2024-07-21 11:11:50.976 INFO 17064 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8080 (http) with context path ''
2024-07-21 11:11:50.984 INFO 17064 --- [ main] com.cherry.chapter1.a03.A03Application : Started A03Application in 1.642 seconds (JVM running for 2.613)
2024-07-21 11:11:51.248 DEBUG 17064 --- [ main] com.cherry.chapter1.a03.LifeCycleBean : 销毁
我们可以看到,执行的流程如下:
- 首先执行Bean的构造方法
- 其次执行Bean的依赖注入方法
- 紧接着执行Bean的初始化方法
- 最后执行Bean的销毁方法
前面我们讲过,Bean后处理器是对Bean生命周期各个阶段的一些扩展,那都有哪些扩展呢?这里举一些例子:
package com.cherry.chapter1.a03;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.PropertyValues;
import org.springframework.beans.factory.config.DestructionAwareBeanPostProcessor;
import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor;
@Component
public class MyBeanPostProcessor implements InstantiationAwareBeanPostProcessor, DestructionAwareBeanPostProcessor {
private static final Logger log = LoggerFactory.getLogger(MyBeanPostProcessor.class);
@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
if (beanName.equals("lifeCycleBean")){
log.debug("<<<< 实例化之前执行,构造方法之前执行");
}
return null;
}
@Override
public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
if (beanName.equals("lifeCycleBean")){
log.debug("<<<< 实例化之后执行,构造方法执行完毕之后执行");
}
return true;
}
@Override
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException {
if (beanName.equals("lifeCycleBean")){
log.debug("<<<< 依赖注入阶段执行.如@Autowird,@Value,@Resource");
}
return pvs;
}
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if (beanName.equals("lifeCycleBean")){
log.debug("<<<< 初始化之前执行,这里返回的对象会替换掉原本的bean, 如@PostConstruct, 2ConfigurationProperties");
}
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (beanName.equals("lifeCycleBean")){
log.debug("<<<< 依赖注入阶段执行,这里返回的对象会替换掉原本的bean,如代理增强");
}
return bean;
}
@Override
public void postProcessBeforeDestruction(Object bean, String beanName) throws BeansException {
if (beanName.equals("lifeCycleBean")){
log.debug("<<<< 销毁前执行,如@PreDestory");
}
}
}
执行结果如下:
2024-07-21 11:43:30.492 DEBUG 6504 --- [ main] c.c.chapter1.a03.MyBeanPostProcessor : <<<< 实例化之前执行,构造方法之前执行
2024-07-21 11:43:30.493 DEBUG 6504 --- [ main] com.cherry.chapter1.a03.LifeCycleBean : 构造方法被调用
2024-07-21 11:43:30.496 DEBUG 6504 --- [ main] c.c.chapter1.a03.MyBeanPostProcessor : <<<< 实例化之后执行,构造方法执行完毕之后执行
2024-07-21 11:43:30.496 DEBUG 6504 --- [ main] c.c.chapter1.a03.MyBeanPostProcessor : <<<< 依赖注入阶段执行.如@Autowird,@Value,@Resource
2024-07-21 11:43:30.497 DEBUG 6504 --- [ main] com.cherry.chapter1.a03.LifeCycleBean : 依赖注入:D:\development_tools\jdk17\jdk-17.0.10
2024-07-21 11:43:30.498 DEBUG 6504 --- [ main] c.c.chapter1.a03.MyBeanPostProcessor : <<<< 初始化之前执行,这里返回的对象会替换掉原本的bean, 如@PostConstruct, 2ConfigurationProperties
2024-07-21 11:43:30.498 DEBUG 6504 --- [ main] com.cherry.chapter1.a03.LifeCycleBean : 初始化
2024-07-21 11:43:30.498 DEBUG 6504 --- [ main] c.c.chapter1.a03.MyBeanPostProcessor : <<<< 依赖注入阶段执行,这里返回的对象会替换掉原本的bean,如代理增强
2024-07-21 11:43:30.840 WARN 6504 --- [ main] o.s.b.a.f.FreeMarkerAutoConfiguration : Cannot find template location(s): [classpath:/templates/] (please add some templates, check your FreeMarker configuration, or set spring.freemarker.checkTemplateLocation=false)
2024-07-21 11:43:30.884 INFO 6504 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8080 (http) with context path ''
2024-07-21 11:43:30.892 INFO 6504 --- [ main] com.cherry.chapter1.a03.A03Application : Started A03Application in 1.932 seconds (JVM running for 3.291)
2024-07-21 11:43:31.166 DEBUG 6504 --- [ main] c.c.chapter1.a03.MyBeanPostProcessor : <<<< 销毁前执行,如@PreDestory
2024-07-21 11:43:31.167 DEBUG 6504 --- [ main] com.cherry.chapter1.a03.LifeCycleBean : 销毁
2. 模板设计模式 Template Method Pattern
举个例子:
package com.cherry.chapter1.a03;
import java.util.ArrayList;
import java.util.List;
public class TesttemplateMethod {
public static void main(String[] args) {
MyBeanFactory beanFactory = new MyBeanFactory();
beanFactory.addBeanPostProcessor(bean -> System.out.println("解析 @Autowired"));
beanFactory.addBeanPostProcessor(bean -> System.out.println("解析 @Resource"));
beanFactory.getBean();
}
// 模板方法 Template Method Pattern
static class MyBeanFactory{
public Object getBean(){
Object bean = new Object();
System.out.println("构造 "+bean);
System.out.println("依赖注入 "+bean);
for (BeanPostProcessor bp:processors){
bp.inject(bean);
}
System.out.println("初始化 "+bean);
return bean;
}
private List<BeanPostProcessor> processors = new ArrayList<>();
public void addBeanPostProcessor(BeanPostProcessor beanPostProcessor){
processors.add(beanPostProcessor);
}
}
static interface BeanPostProcessor {
public void inject(Object bean); // 对依赖注入阶段的扩展
}
}
运行结果如下:
构造 java.lang.Object@4b6995df
依赖注入 java.lang.Object@4b6995df
解析 @Autowired
解析 @Resource
初始化 java.lang.Object@4b6995df
模板方法的核心就是将不能确定的部分抽象为一个接口,将来在特定的时机调用抽象方法,通过回调的方式对接口中的功能进行扩展。
分类:
Spring 高级49讲
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构