Bean 生命周期全解析 - 从实例化到销毁的完整旅程
IoC 容器的核心职责之一就是管理 Bean 的生命周期。理解 Bean 从创建到销毁的每一个环节,是掌握 Spring 框架内功的关键。
概述
Spring IoC 容器管理的 Bean 并非简单的 Java 对象。容器在创建 Bean 的过程中,会穿插执行一系列回调接口和扩展点,形成了一个完整且可干预的生命周期。
一个典型的 Singleton Bean 生命周期包含以下阶段:
容器启动
│
▼
┌─────────────────────────────┐
│ 1. 实例化(Instantiation) │ ← new 对象,分配内存
└─────────────────────────────┘
│
▼
┌─────────────────────────────┐
│ 2. 属性赋值(Populate) │ ← 设置依赖属性、自动注入
└─────────────────────────────┘
│
▼
┌─────────────────────────────┐
│ 3. Aware 接口回调 │ ← 注入容器基础设施
└─────────────────────────────┘
│
▼
┌─────────────────────────────┐
│ 4. BeanPostProcessor │ ← postProcessBeforeInitialization
└─────────────────────────────┘
│
▼
┌─────────────────────────────┐
│ 5. 初始化(Initialization)│ ← @PostConstruct / InitializingBean / init-method
└─────────────────────────────┘
│
▼
┌─────────────────────────────┐
│ 6. BeanPostProcessor │ ← postProcessAfterInitialization
└─────────────────────────────┘
│
▼
Bean 就绪 — 可供应用使用
│
│ ... 运行期间 ...
│
▼ (容器关闭)
┌─────────────────────────────┐
│ 7. 销毁(Destruction) │ ← @PreDestroy / DisposableBean / destroy-method
└─────────────────────────────┘完整时序图(文字描述)
ApplicationContext
│
├── 1. 调用 BeanFactory.getBean()
│
├── 2. 实例化前
│ └── InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation()
│
├── 3. 实例化
│ └── 通过反射/工厂方法创建对象
│
├── 4. 实例化后
│ └── InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation()
│
├── 5. 属性赋值
│ ├── InstantiationAwareBeanPostProcessor.postProcessProperties()
│ └── 填充普通属性、自动注入依赖
│
├── 6. 设置 Bean 名称
│ └── BeanNameAware.setBeanName()
│
├── 7. 设置 Bean 工厂
│ └── BeanFactoryAware.setBeanFactory()
│
├── 8. 设置应用上下文
│ └── ApplicationContextAware.setApplicationContext()
│
├── 9. BeanPostProcessor 前置处理
│ └── BeanPostProcessor.postProcessBeforeInitialization()
│
├── 10. 初始化
│ ├── @PostConstruct 注解方法
│ ├── InitializingBean.afterPropertiesSet()
│ └── 自定义 init-method
│
├── 11. BeanPostProcessor 后置处理
│ └── BeanPostProcessor.postProcessAfterInitialization()
│
├── ▶ 12. Bean 就绪,提供服务
│
└── 13. 容器关闭,销毁
├── @PreDestroy 注解方法
├── DisposableBean.destroy()
└── 自定义 destroy-method各阶段详细说明
1. 实例化(Instantiation)
源码入口:AbstractAutowireCapableBeanFactory.createBeanInstance()
Spring 通过以下方式创建 Bean 实例:
- 反射调用构造器:默认使用无参构造器,或根据参数自动选择合适的构造器
- 工厂方法:通过
@Bean注解或 XML<bean factory-method="">配置 - Supplier:
BeanDefinition.setInstanceSupplier()
// AbstractAutowireCapableBeanFactory 核心流程
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
// 1. 检查是否有 Supplier
// 2. 检查是否有工厂方法
// 3. 构造器自动推断(Autowire Constructor)
// 4. 默认无参构造器
}此阶段有一个重要扩展点:InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation(),可以在容器真正实例化之前返回代理对象,跳过后面的生命周期流程。
2. 属性赋值(Populate)
源码入口:AbstractAutowireCapableBeanFactory.populateBean()
属性赋值阶段完成以下工作:
- 根据
BeanDefinition中的PropertyValues设置普通属性 - 执行
@Autowired/@Resource/@Inject等依赖注入 - 调用
InstantiationAwareBeanPostProcessor.postProcessProperties()处理自定义注入逻辑
// populateBean 核心流程(简化)
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
// 1. 调用 postProcessAfterInstantiation(),跳过属性赋值
// 2. 调用 postProcessProperties(),处理 @Autowired 等注解
// 3. 应用 PropertyValues 设置 XML / Java Config 定义的属性
}3. Aware 接口回调
源码入口:AbstractAutowireCapableBeanFactory.invokeAwareMethods() + ApplicationContextAwareProcessor
回调顺序(按接口):
| Aware 接口 | 作用 | 调用时机 |
|---|---|---|
BeanNameAware | 获取 Bean 在容器中的名称 | setBeanName() |
BeanClassLoaderAware | 获取加载 Bean 的 ClassLoader | setBeanClassLoader() |
BeanFactoryAware | 获取所属的 BeanFactory | setBeanFactory() |
EnvironmentAware | 获取 Environment 环境信息 | setEnvironment() |
EmbeddedValueResolverAware | 获取占位符解析器 | setEmbeddedValueResolver() |
ResourceLoaderAware | 获取 ResourceLoader | setResourceLoader() |
ApplicationEventPublisherAware | 获取事件发布器 | setApplicationEventPublisher() |
MessageSourceAware | 获取国际化资源 | setMessageSource() |
ApplicationContextAware | 获取 ApplicationContext | setApplicationContext() |
前三个 Aware 由 AbstractAutowireCapableBeanFactory.invokeAwareMethods() 直接调用,后六个由 ApplicationContextAwareProcessor(一个 BeanPostProcessor)在 postProcessBeforeInitialization 中调用。
// 容器内部实现
private void invokeAwareMethods(String beanName, Object bean) {
if (bean instanceof Aware) {
if (bean instanceof BeanNameAware) {
((BeanNameAware) bean).setBeanName(beanName);
}
if (bean instanceof BeanClassLoaderAware) {
((BeanClassLoaderAware) bean).setBeanClassLoader(getBeanClassLoader());
}
if (bean instanceof BeanFactoryAware) {
((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
}
}
}4. BeanPostProcessor 前置处理
源码入口:AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsBeforeInitialization()
在初始化之前,容器会遍历所有注册的 BeanPostProcessor,调用其 postProcessBeforeInitialization() 方法。这是 Spring 提供的最强大的扩展点之一,可以在此对 Bean 进行包装、替换、增强。
5. 初始化(Initialization)
源码入口:AbstractAutowireCapableBeanFactory.invokeInitMethods()
Bean 的初始化逻辑执行顺序(严格有序):
- @PostConstruct 注解方法 — 通过
CommonAnnotationBeanPostProcessor.postProcessBeforeInitialization()触发 - InitializingBean.afterPropertiesSet() — 由容器直接调用
- 自定义 init-method — 通过反射调用
@Bean(initMethod = "...")或 XML 配置的初始化方法
// 初始化调用顺序源码
protected void invokeInitMethods(String beanName, Object bean, @Nullable RootBeanDefinition mbd) throws Throwable {
// 检查是否实现了 InitializingBean
boolean isInitializingBean = (bean instanceof InitializingBean);
if (isInitializingBean && !(mbd != null && mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
// 第一阶段:调用 InitializingBean.afterPropertiesSet()
((InitializingBean) bean).afterPropertiesSet();
}
// 第二阶段:调用自定义 init-method(跳过已经被 afterPropertiesSet 覆盖的情况)
if (mbd != null && bean.getClass() != NullBean.class) {
String initMethodName = mbd.getInitMethodName();
if (StringUtils.hasLength(initMethodName) &&
!(isInitializingBean && "afterPropertiesSet".equals(initMethodName))) {
invokeCustomInitMethod(beanName, bean, mbd);
}
}
}注意:
@PostConstruct实际上是靠CommonAnnotationBeanPostProcessor(一个BeanPostProcessor)在postProcessBeforeInitialization中调用的,因此它的执行时机要早于invokeInitMethods()。完整的时序是:所有BeanPostProcessor.postProcessBeforeInitialization()执行完毕后,再进入invokeInitMethods()。
6. BeanPostProcessor 后置处理
源码入口:AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsAfterInitialization()
初始化完成后,容器会调用所有 BeanPostProcessor 的 postProcessAfterInitialization() 方法。这是创建 AOP 代理的经典时机——AbstractAutoProxyCreator 正是在此阶段为 Bean 生成代理对象。
7. 销毁(Destruction)
源码入口:DisposableBeanAdapter.destroy()
容器关闭时,按照与初始化相反的顺序执行销毁逻辑:
- @PreDestroy 注解方法 — 通过
CommonAnnotationBeanPostProcessor.postProcessBeforeDestruction()触发 - DisposableBean.destroy() — 由容器直接调用
- 自定义 destroy-method — 通过反射调用
@Bean(destroyMethod = "...")或 XML 配置的销毁方法
// 销毁调用顺序源码
public void destroy() {
// 第一阶段:调用 @PreDestroy 注解方法
// (由 CommonAnnotationBeanPostProcessor 在 ApplicationContext 关闭时触发)
// 第二阶段:调用 DisposableBean.destroy()
if (this.invokeDisposableBean) {
((DisposableBean) this.bean).destroy();
}
// 第三阶段:调用自定义 destroy-method
if (this.destroyMethod != null) {
invokeCustomDestroyMethod(this.destroyMethod);
}
}BeanPostProcessor 详解
核心接口
public interface BeanPostProcessor {
// Bean 初始化之前调用
@Nullable
default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
// Bean 初始化之后调用
@Nullable
default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
}执行时机定位
实例化 → 属性赋值 → Aware 回调
│
▼
┌──────────────────────┐
│ postProcessBefore │ ← @PostConstruct 在这里执行
│ Initialization() │ ← CommonAnnotationBeanPostProcessor
└──────────────────────┘
│
▼
┌──────────────────────┐
│ 初始化阶段 │ ← InitializingBean / init-method
└──────────────────────┘
│
▼
┌──────────────────────┐
│ postProcessAfter │ ← AOP 代理在这里创建
│ Initialization() │ ← AbstractAutoProxyCreator
└──────────────────────┘重要的内置 BeanPostProcessor
| 实现类 | 作用 |
|---|---|
ApplicationContextAwareProcessor | 注入 ApplicationContext 相关 Aware |
CommonAnnotationBeanPostProcessor | 处理 @PostConstruct / @PreDestroy / @Resource |
AutowiredAnnotationBeanPostProcessor | 处理 @Autowired / @Value / @Inject |
AbstractAutoProxyCreator | AOP 自动代理创建(声明式事务、@Aspect 等的基础) |
PersistenceExceptionTranslationPostProcessor | 数据库异常翻译 |
初始化方法执行顺序验证
验证示例
@Component
public class LifecycleDemoBean implements InitializingBean {
private String name;
public LifecycleDemoBean() {
System.out.println("[1] 构造方法执行");
}
public void setName(String name) {
this.name = name;
System.out.println("[2] 设置属性: " + name);
}
@Override
public void setBeanName(String name) {
System.out.println("[3] BeanNameAware: " + name);
}
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
System.out.println("[4] BeanFactoryAware");
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
System.out.println("[5] ApplicationContextAware");
}
@PostConstruct
public void postConstruct() {
System.out.println("[6] @PostConstruct 执行");
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("[7] InitializingBean.afterPropertiesSet() 执行");
}
@Bean(initMethod = "customInit")
public LifecycleDemoBean lifecycleDemoBean() {
return new LifecycleDemoBean();
}
public void customInit() {
System.out.println("[8] customInit-method 执行");
}
}执行输出:
[1] 构造方法执行
[2] 设置属性: demoBean
[3] BeanNameAware: lifecycleDemoBean
[4] BeanFactoryAware
[5] ApplicationContextAware
[BeanPostProcessor BeforeInitialization]
[6] @PostConstruct 执行
[7] InitializingBean.afterPropertiesSet() 执行
[8] customInit-method 执行
[BeanPostProcessor AfterInitialization]实战案例:电商订单全链路耗时追踪
在电商订单服务中,我们常需要监控每个服务方法的执行耗时,以便定位性能瓶颈。下面的案例演示如何通过自定义注解 + BeanPostProcessor 实现零侵入的全链路耗时追踪。
1. 定义 @LogExecutionTime 注解
package com.example.ecommerce.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 标记需要记录执行耗时的方法。
* 通过 BeanPostProcessor 自动为标记该注解的 Bean 生成代理,
* 实现无侵入的性能监控。
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface LogExecutionTime {
/** 业务操作名称,默认使用方法名 */
String value() default "";
/** 慢查询阈值(毫秒),超过该值打印警告日志 */
long slowThreshold() default 1000L;
}2. 实现 TimeLoggingBeanPostProcessor
package com.example.ecommerce.config;
import com.example.ecommerce.annotation.LogExecutionTime;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.stereotype.Component;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* BeanPostProcessor 实现 —— 为带有 @LogExecutionTime 注解方法的 Bean
* 自动创建代理,在方法执行前后记录耗时。
*
* 使用 CGLIB 动态代理,支持类代理和接口代理。
*/
@Slf4j
@Component
public class TimeLoggingBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
Class<?> targetClass = bean.getClass();
// 检查当前 Bean 是否有方法标注了 @LogExecutionTime
boolean hasAnnotatedMethod = false;
for (Method method : targetClass.getDeclaredMethods()) {
if (AnnotationUtils.findAnnotation(method, LogExecutionTime.class) != null) {
hasAnnotatedMethod = true;
break;
}
}
// 还需要检查父类/接口中的方法
if (!hasAnnotatedMethod) {
hasAnnotatedMethod = hasAnnotatedOnInterfaces(targetClass);
}
if (!hasAnnotatedMethod) {
return bean; // 无注解方法,直接返回原始 Bean
}
log.info("[TimeLogging] 为 Bean '{}' 创建耗时追踪代理", beanName);
// 如果 Bean 有接口,使用 JDK 动态代理
Class<?>[] interfaces = targetClass.getInterfaces();
if (interfaces.length > 0) {
return Proxy.newProxyInstance(
targetClass.getClassLoader(),
interfaces,
(proxy, method, args) -> invokeWithTiming(bean, method, args)
);
}
// 否则使用 CGLIB 代理
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(targetClass);
enhancer.setCallback((MethodInterceptor) (obj, method, args, methodProxy) ->
invokeWithTiming(bean, method, args));
return enhancer.create();
}
/**
* 带耗时统计的方法调用
*/
private Object invokeWithTiming(Object target, Method method, Object[] args) throws Throwable {
LogExecutionTime annotation = AnnotationUtils.findAnnotation(
target.getClass().getDeclaredMethod(method.getName(), method.getParameterTypes()),
LogExecutionTime.class);
// 如果从目标类找不到注解,从原始 bean 类查找
if (annotation == null) {
annotation = AnnotationUtils.findAnnotation(method, LogExecutionTime.class);
}
if (annotation == null) {
// 没有注解直接执行
return method.invoke(target, args);
}
String operationName = annotation.value().isEmpty()
? method.getDeclaringClass().getSimpleName() + "#" + method.getName()
: annotation.value();
long slowThreshold = annotation.slowThreshold();
long start = System.currentTimeMillis();
try {
return method.invoke(target, args);
} finally {
long elapsed = System.currentTimeMillis() - start;
if (elapsed >= slowThreshold) {
log.warn("[慢查询] {} 执行耗时 {}ms,超过阈值 {}ms", operationName, elapsed, slowThreshold);
} else {
log.info("[性能监控] {} 执行耗时 {}ms", operationName, elapsed);
}
}
}
/**
* 检查接口中的方法是否标注了 @LogExecutionTime
*/
private boolean hasAnnotatedOnInterfaces(Class<?> clazz) {
for (Class<?> iface : clazz.getInterfaces()) {
for (Method method : iface.getDeclaredMethods()) {
if (AnnotationUtils.findAnnotation(method, LogExecutionTime.class) != null) {
return true;
}
}
}
return false;
}
}3. 在订单服务中使用
package com.example.ecommerce.service;
import com.example.ecommerce.annotation.LogExecutionTime;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.math.BigDecimal;
import java.util.concurrent.TimeUnit;
/**
* 订单服务 —— 通过 @LogExecutionTime 自动监控核心业务方法耗时。
*/
@Slf4j
@Service
@RequiredArgsConstructor
public class OrderService {
private final InventoryService inventoryService;
private final PaymentService paymentService;
private final NotificationService notificationService;
/**
* 创建订单 —— 核心链路,监控完整耗时
*/
@LogExecutionTime(value = "创建订单", slowThreshold = 2000L)
@Transactional
public Order createOrder(OrderRequest request) {
log.info("开始创建订单: userId={}, productId={}", request.getUserId(), request.getProductId());
// 1. 扣减库存
inventoryService.deduct(request.getProductId(), request.getQuantity());
// 2. 创建订单记录
Order order = new Order();
order.setUserId(request.getUserId());
order.setProductId(request.getProductId());
order.setQuantity(request.getQuantity());
order.setAmount(request.getPrice().multiply(BigDecimal.valueOf(request.getQuantity())));
order.setStatus(OrderStatus.PENDING_PAYMENT);
save(order);
// 3. 发起支付
paymentService.pay(order);
// 4. 发送通知
notificationService.sendOrderConfirmation(order);
return order;
}
/**
* 查询订单 —— 监控数据库查询耗时
*/
@LogExecutionTime(value = "查询订单")
public Order getOrder(Long orderId) {
// 模拟数据库查询
simulateDelay(50);
return orderRepository.findById(orderId)
.orElseThrow(() -> new RuntimeException("订单不存在: " + orderId));
}
/**
* 取消订单 —— 标记慢查询阈值为 500ms
*/
@LogExecutionTime(value = "取消订单", slowThreshold = 500L)
@Transactional
public void cancelOrder(Long orderId) {
Order order = getOrder(orderId);
order.setStatus(OrderStatus.CANCELLED);
save(order);
// 回退库存
inventoryService.restore(order.getProductId(), order.getQuantity());
// 发起退款
paymentService.refund(order);
}
private void save(Order order) {
// 模拟数据库保存
orderRepository.save(order);
}
private void simulateDelay(long millis) {
try {
TimeUnit.MILLISECONDS.sleep(millis);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}4. 库存服务
package com.example.ecommerce.service;
import com.example.ecommerce.annotation.LogExecutionTime;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import java.util.concurrent.TimeUnit;
@Slf4j
@Service
public class InventoryService {
@LogExecutionTime(value = "扣减库存")
public void deduct(Long productId, Integer quantity) {
log.info("扣减库存: productId={}, quantity={}", productId, quantity);
// 模拟 Redis 缓存扣减 + DB 持久化
simulateDelay(30);
}
@LogExecutionTime(value = "回退库存")
public void restore(Long productId, Integer quantity) {
log.info("回退库存: productId={}, quantity={}", productId, quantity);
simulateDelay(20);
}
private void simulateDelay(long millis) {
try {
TimeUnit.MILLISECONDS.sleep(millis);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}5. 运行效果
启动应用后,调用 orderService.createOrder(...) 方法时,控制台输出:
[性能监控] 扣减库存 执行耗时 32ms
[性能监控] 发起支付 执行耗时 156ms
[性能监控] 发送通知 执行耗时 12ms
[性能监控] 创建订单 执行耗时 201ms如果某个环节耗时超过阈值(如 createOrder 的阈值设为 2000ms),则会输出警告:
[慢查询] 创建订单 执行耗时 3521ms,超过阈值 2000ms实现要点总结
| 要点 | 说明 |
|---|---|
| 无侵入 | 业务代码只需加一个注解,无需修改方法体 |
| 动态代理 | BeanPostProcessor 在 postProcessAfterInitialization 中创建代理 |
| 阈值分级 | 每个方法可独立设置慢查询阈值,灵活监控 |
| 全链路追踪 | 从 Controller → Service → DAO 各层均可标注,形成完整调用链耗时视图 |
总结
| 阶段 | 关键扩展点 | 典型用途 |
|---|---|---|
| 实例化前 | postProcessBeforeInstantiation | 返回代理对象替代正常创建 |
| 实例化 | 构造器/工厂方法 | 对象创建 |
| 属性赋值 | postProcessProperties | 自定义注入逻辑 |
| Aware 回调 | BeanNameAware 等 | 获取容器基础设施 |
| 初始化前 | postProcessBeforeInitialization | @PostConstruct、参数校验 |
| 初始化 | afterPropertiesSet / init-method | 初始化资源 |
| 初始化后 | postProcessAfterInitialization | AOP 代理创建 |
| 销毁前 | postProcessBeforeDestruction | @PreDestroy |
| 销毁 | destroy / destroy-method | 释放资源 |
Spring Bean 生命周期不仅是一个创建和销毁的过程,更是一套精心设计的扩展点体系。理解这背后的设计哲学,能让你在遇到复杂的框架集成、性能监控、安全增强等需求时,精准地找到正确的切入位置。
参考源码
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactoryorg.springframework.beans.factory.config.BeanPostProcessororg.springframework.beans.factory.InitializingBeanorg.springframework.beans.factory.DisposableBeanorg.springframework.beans.factory.support.DisposableBeanAdapterorg.springframework.context.support.ApplicationContextAwareProcessororg.springframework.context.annotation.CommonAnnotationBeanPostProcessor