Spring Bean生命周期
约 1499 字大约 5 分钟
springbean
2025-03-24
概述
Spring Bean 的生命周期是 Spring 框架最核心的知识点之一。从 BeanDefinition 到 Bean 实例的创建、初始化、使用直到销毁,Spring 容器对整个过程提供了丰富的扩展点。理解这些扩展点,是开发自定义框架、中间件集成的基础。
Bean 生命周期全景图
阶段一:实例化(Instantiation)
Spring 通过反射或 CGLIB 创建 Bean 实例。在实例化前后,InstantiationAwareBeanPostProcessor 提供了扩展点。
@Component
public class CustomInstantiationProcessor implements InstantiationAwareBeanPostProcessor {
@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) {
if (beanClass == SpecialService.class) {
// 返回非null则跳过Spring默认实例化,直接使用返回的对象
System.out.println("Before instantiation: " + beanName);
}
return null; // 返回null继续正常实例化流程
}
@Override
public boolean postProcessAfterInstantiation(Object bean, String beanName) {
// 返回false则跳过属性填充阶段
return true;
}
}实例化方式
// 1. 构造器实例化(最常见)
@Component
public class UserService {
private final UserRepository userRepository;
@Autowired
public UserService(UserRepository userRepository) {
this.userRepository = userRepository;
}
}
// 2. 工厂方法实例化
@Configuration
public class AppConfig {
@Bean
public RestTemplate restTemplate() {
return new RestTemplateBuilder()
.setConnectTimeout(Duration.ofSeconds(5))
.build();
}
}
// 3. FactoryBean 实例化
public class ConnectionFactoryBean implements FactoryBean<Connection> {
@Override
public Connection getObject() throws Exception {
return DriverManager.getConnection(url, username, password);
}
@Override
public Class<?> getObjectType() {
return Connection.class;
}
}阶段二:属性填充(Property Population)
实例化后,Spring 通过依赖注入填充 Bean 的属性。支持字段注入、Setter 注入和构造器注入。
@Service
public class OrderService {
// 字段注入(不推荐,测试不友好)
@Autowired
private PaymentService paymentService;
// Setter 注入
private NotificationService notificationService;
@Autowired
public void setNotificationService(NotificationService notificationService) {
this.notificationService = notificationService;
}
// 构造器注入(推荐)
private final OrderRepository orderRepository;
public OrderService(OrderRepository orderRepository) {
this.orderRepository = orderRepository;
}
}阶段三:Aware 接口回调
Spring 提供了一系列 Aware 接口,让 Bean 获取容器相关的资源:
@Component
public class ContextAwareService implements
BeanNameAware,
BeanFactoryAware,
ApplicationContextAware,
EnvironmentAware {
private String beanName;
private BeanFactory beanFactory;
private ApplicationContext applicationContext;
private Environment environment;
@Override
public void setBeanName(String name) {
this.beanName = name;
System.out.println("1. BeanNameAware: " + name);
}
@Override
public void setBeanFactory(BeanFactory beanFactory) {
this.beanFactory = beanFactory;
System.out.println("2. BeanFactoryAware");
}
@Override
public void setEnvironment(Environment environment) {
this.environment = environment;
System.out.println("3. EnvironmentAware");
}
@Override
public void setApplicationContext(ApplicationContext ctx) {
this.applicationContext = ctx;
System.out.println("4. ApplicationContextAware");
}
}阶段四:初始化(Initialization)
初始化阶段有三种方式,执行顺序固定:
@Component
public class DataSourceInitializer implements InitializingBean {
@Value("${db.url}")
private String dbUrl;
// 1. 最先执行:@PostConstruct(JSR-250标准)
@PostConstruct
public void postConstruct() {
System.out.println("1. @PostConstruct - 验证配置");
Objects.requireNonNull(dbUrl, "db.url must not be null");
}
// 2. 其次执行:InitializingBean 接口
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("2. InitializingBean.afterPropertiesSet - 初始化连接池");
}
// 3. 最后执行:自定义 init-method
// 通过 @Bean(initMethod = "customInit") 指定
public void customInit() {
System.out.println("3. custom init-method - 预热缓存");
}
}阶段五:BeanPostProcessor 拦截
BeanPostProcessor 在初始化前后提供拦截点,是 Spring AOP、注解处理等核心功能的实现基础。
@Component
public class AuditBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) {
// 在 @PostConstruct 之前执行
if (bean.getClass().isAnnotationPresent(Auditable.class)) {
System.out.println("Registering auditable bean: " + beanName);
}
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) {
// 在所有初始化方法之后执行
// AOP代理就是在这里创建的
if (bean.getClass().isAnnotationPresent(Auditable.class)) {
return createAuditProxy(bean);
}
return bean;
}
private Object createAuditProxy(Object bean) {
// 创建代理对象...
return bean;
}
}阶段六:销毁(Destruction)
当容器关闭时,Spring 按照与初始化相反的逻辑执行销毁操作:
@Component
public class ResourceManager implements DisposableBean {
private ExecutorService executorService;
@PostConstruct
public void init() {
executorService = Executors.newFixedThreadPool(10);
}
// 1. 最先执行:@PreDestroy
@PreDestroy
public void preDestroy() {
System.out.println("1. @PreDestroy - 停止接收新任务");
executorService.shutdown();
}
// 2. 其次执行:DisposableBean 接口
@Override
public void destroy() throws Exception {
System.out.println("2. DisposableBean.destroy - 等待任务完成");
executorService.awaitTermination(30, TimeUnit.SECONDS);
}
// 3. 最后执行:自定义 destroy-method
// 通过 @Bean(destroyMethod = "cleanup") 指定
public void cleanup() {
System.out.println("3. custom destroy-method - 清理临时文件");
}
}确保优雅关闭:
@SpringBootApplication
public class Application {
public static void main(String[] args) {
ConfigurableApplicationContext ctx = SpringApplication.run(Application.class, args);
// 注册JVM关闭钩子,确保容器优雅关闭
ctx.registerShutdownHook();
}
}不同 Scope 的生命周期差异
@Component
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public class PrototypeBean {
@PreDestroy
public void destroy() {
// 注意:Prototype Bean 的 @PreDestroy 不会被 Spring 容器自动调用!
// 需要调用方手动管理
}
}
// Singleton 注入 Prototype 的正确方式
@Component
public class SingletonBean {
@Autowired
private ObjectProvider<PrototypeBean> prototypeBeanProvider;
public void doSomething() {
// 每次调用 getObject() 获取新实例
PrototypeBean prototype = prototypeBeanProvider.getObject();
}
}完整生命周期验证
@Component
public class LifecycleBean implements
BeanNameAware,
BeanFactoryAware,
ApplicationContextAware,
InitializingBean,
DisposableBean {
public LifecycleBean() {
System.out.println("1. 构造方法");
}
@Autowired
public void setDependency(SomeDependency dep) {
System.out.println("2. 属性注入");
}
@Override
public void setBeanName(String name) {
System.out.println("3. BeanNameAware.setBeanName: " + name);
}
@Override
public void setBeanFactory(BeanFactory bf) {
System.out.println("4. BeanFactoryAware.setBeanFactory");
}
@Override
public void setApplicationContext(ApplicationContext ctx) {
System.out.println("5. ApplicationContextAware.setApplicationContext");
}
// BeanPostProcessor.postProcessBeforeInitialization 在此执行
@PostConstruct
public void postConstruct() {
System.out.println("6. @PostConstruct");
}
@Override
public void afterPropertiesSet() {
System.out.println("7. InitializingBean.afterPropertiesSet");
}
// BeanPostProcessor.postProcessAfterInitialization 在此执行
// === Bean 就绪可用 ===
@PreDestroy
public void preDestroy() {
System.out.println("8. @PreDestroy");
}
@Override
public void destroy() {
System.out.println("9. DisposableBean.destroy");
}
}总结
Spring Bean 生命周期涵盖实例化、属性填充、Aware 回调、BeanPostProcessor 处理、初始化、使用和销毁七个主要阶段。每个阶段都提供了扩展点,允许开发者在 Bean 的不同生命节点注入自定义逻辑。理解这些扩展点的执行顺序和适用场景,是掌握 Spring 框架高级特性的基础。推荐优先使用 @PostConstruct / @PreDestroy 等标准注解,保持代码与 Spring API 的低耦合。
贡献者
更新日志
2026/3/14 13:09
查看所有更新日志
9f6c2-feat: organize wiki content and refresh site setup于