当前位置: 首页 > news >正文

深入剖析Spring Bean生命周期:从诞生到消亡的全过程

作为Java开发者最熟悉的框架,Spring的核心就是Bean的管理。但你真的了解一个Bean从创建到销毁的完整生命周期吗?本文将带你深入Spring内部,完整解析Bean生命周期的每个关键阶段!

一、容器启动阶段:Bean的"孕育期"

1. Bean定义加载

Spring容器启动时,会读取所有配置源,获取Bean的定义信息,为Bean信息的注册做准备:

// 配置来源示例
@Configuration
public class AppConfig {@Bean(initMethod = "init", destroyMethod = "cleanup")public MyBean myBean() {return new MyBean();}
}
  • 支持XML/注解/Java配置三种方式定义Bean对象
  • 最终都会解析为BeanDefinition对象

2. BeanDefinitionRegistryPostProcessor干预

BeanDefinitionRegistryPostProcessor是Spring框架中比BeanFactoryPostProcessor更强大的扩展点,允许在标准Bean定义加载后、但在Bean实例化前对Bean定义注册表进行更底层的操作。

@Component
public class MyRegistryPostProcessor implements
BeanDefinitionRegistryPostProcessor, PriorityOrdered {@Overridepublic void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {// 动态注册新Bean(如MyBatis的Mapper扫描)registry.registerBeanDefinition("dynamicBean", new RootBeanDefinition(DynamicBean.class));}@Overridepublic int getOrder() {return 0; // 最高优先级}
}

典型应用场景:

  • MyBatis的MapperScannerConfigurer,实现自动扫描和注册MyBatis的Mapper接口
  • Spring Boot的条件装配(@Conditional),实现自动装配
  • 动态注册Bean

三种控制方式(优先级由高到低):

  • PriorityOrdered接口:最高优先级
public class MyProcessor implements BeanDefinitionRegistryPostProcessor, PriorityOrdered {@Overridepublic int getOrder() { return 0; }
}
  • Ordered接口:中等优先级
public class MyProcessor implements BeanDefinitionRegistryPostProcessor, Ordered {@Overridepublic int getOrder() { return 100; }
}
  • 无顺序接口:自然顺序(不保证确定顺序)

3. BeanFactoryPostProcessor干预

BeanFactoryPostProcessor是Spring框架中用于在Bean工厂初始化后、Bean实例化前对Bean定义进行修改的扩展点。理解其执行顺序对于解决复杂的Spring配置问题非常重要。

@Component
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {@Overridepublic void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {BeanDefinition bd = beanFactory.getBeanDefinition("myBean");bd.setScope(ConfigurableBeanFactory.SCOPE_PROTOTYPE);bd.setLazyInit(true);}
}

注意执行顺序:

  1. 实现PriorityOrdered接口的处理器,优先级最高
  2. 实现Ordered接口的处理器,优先级次之
  3. 常规处理器,最后执行

对于同级别处理器按 getOrder()返回值排序(值越小优先级越高),当未指定顺序时,执行顺序不确定。

二、实例化阶段:Bean的"出生"

4. InstantiationAwareBeanPostProcessor前置处理

InstantiationAwareBeanPostProcessor是Spring容器中功能强大的扩展接口,允许在Bean实例化前后进行拦截和处理。其前置处理能力为开发者提供了在Bean生命周期早期介入的机会。

@Component
public class MyInstantiationProcessor implements
InstantiationAwareBeanPostProcessor {@Overridepublic Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) {if ("myService".equals(beanName)) {return Proxy.newProxyInstance(...); // 返回代理对象}return null; // 继续默认实例化}
}

典型应用:

  • Spring AOP的AbstractAutoProxyCreator,实现自动代理创建的核心抽象类,为 Spring 的声明式事务管理、缓存、安全等 AOP 功能提供了基础支持
  • 跳过特定Bean的实例化

5. 真正的实例化过程

通过以下方式创建实例:

  • 构造函数反射(最常见)
  • 静态工厂方法
  • 实例工厂方法

此时得到的只是"裸实例",所有依赖都未注入!

三、依赖注入阶段:Bean的"成长"

6. InstantiationAwareBeanPostProcessor属性处理

InstantiationAwareBeanPostProcessor在Spring属性处理阶段扮演着关键角色,提供了对依赖注入过程的精细控制。其中postProcessAfterInstantiation后实例化拦截阶段,在对象实例化后(构造函数执行完成),属性注入前执行;而postProcessProperties则是属性值应用前最后修改机会(Spring 5.1+推荐)。

@Override
public boolean postProcessAfterInstantiation(Object bean, String beanName) {if (bean instanceof SpecialBean) {// 手动设置属性,跳过Spring自动注入((SpecialBean) bean).setSpecialProperty("manual");return false; // 阻止后续属性注入}return true; // 允许正常注入
}@Override
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {if (bean instanceof ConfigurableBean) {MutablePropertyValues mpvs = (MutablePropertyValues) pvs;mpvs.add("timeout", 5000); // 覆盖配置值}return pvs;
}

典型使用场景:

  • 实现动态属性注入
@Override
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {if (bean instanceof EnvironmentAwareBean) {MutablePropertyValues values = new MutablePropertyValues(pvs);values.add("environment", determineRuntimeEnvironment());return values;}return pvs;
}
  • 属性值的转换
@Override
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {if (bean instanceof DateFormatBean) {MutablePropertyValues mpvs = new MutablePropertyValues(pvs);if (mpvs.contains("datePattern")) {String pattern = (String) mpvs.get("datePattern");mpvs.add("formatter", new SimpleDateFormat(pattern));}return mpvs;}return pvs;
}
  • 条件属性的注入
@Override
public boolean postProcessAfterInstantiation(Object bean, String beanName) {if (bean instanceof FeatureToggleBean) {// 根据特性开关决定是否注入return featureManager.isEnabled("dynamic_injection");}return true;
}

7. 依赖注入的完整流程

public class ExampleService {
@Autowired
private UserRepository repository;@Value("${app.timeout}")private int timeout;
}

注入顺序(优先级从高到低):

  1. @Autowired字段注入,最先注入
  2. @Autowired方法注入,其次注入
  3. @Resource注入,随后注入
  4. @Value(“${app.timeout}”),最后执行的值注入

四、Aware接口回调:获取容器"超能力"

Spring 框架中的 Aware 接口是一组特殊的回调接口,允许 Bean 获取容器的基础设施对象。这些回调在 Bean 生命周期的特定阶段执行,为 Bean 提供了与容器交互的能力。

完整的Aware接口调用顺序

@Component
public class AllAwareBean implements BeanNameAware, BeanClassLoaderAware,
BeanFactoryAware, EnvironmentAware, ResourceLoaderAware, ApplicationEventPublisherAware, MessageSourceAware, ApplicationContextAware {// 按以下顺序调用:@Override public void setBeanName(String name) {}@Override public void setBeanClassLoader(ClassLoader cl) {}@Override public void setBeanFactory(BeanFactory bf) {}@Override public void setEnvironment(Environment env) {}@Override public void setResourceLoader(ResourceLoader rl) {}@Override public void setApplicationEventPublisher(ApplicationEventPublisher aep) {}@Override public void setMessageSource(MessageSource ms) {}@Override public void setApplicationContext(ApplicationContext ctx) {}
}

五、初始化阶段:Bean的"成人礼"

初始化流程详解

Spring容器中Bean的初始化方法执行可以分为三个层次,依次为@PostConstruct注解方法、实现InitializingBean接口并重写afterPropertiesSet方法、XML中指定自定义的init-method。

@Component
public class InitBean {// 1. @PostConstruct(最先执行)@PostConstructpublic void postConstruct() {System.out.println("@PostConstruct");}// 2. InitializingBean接口@Overridepublic void afterPropertiesSet() {System.out.println("InitializingBean");}// 3. 自定义init方法public void customInit() {System.out.println("custom init");}
}

BeanPostProcessor的处理

BeanPostProcessor 是 Spring 框架中最核心的扩展接口之一,为开发者提供了在 Bean 初始化前后进行自定义处理的强大能力。

@Component
public class MyBeanPostProcessor implements BeanPostProcessor, Ordered {@Overridepublic Object postProcessBeforeInitialization(Object bean, String beanName) {if (bean instanceof MyBean) {System.out.println("BeforeInit: " + beanName);}return bean;}@Overridepublic Object postProcessAfterInitialization(Object bean, String beanName) {if (bean instanceof MyBean) {System.out.println("AfterInit: " + beanName);// AOP代理通常在此生成return Enhancer.create(...);}return bean;}@Overridepublic int getOrder() {return Ordered.LOWEST_PRECEDENCE;}
}

前置处理的典型应用场景:

  • 注解处理(如 @PostConstruct)
  • 元数据准备
  • 代理预处理

后置处理的典型应用场景:

  • AOP代理创建
  • 包装对象生成
  • 最终检查

六、使用阶段:Bean的"黄金时期"

此时Bean已经完全初始化:

  • 可以通过ApplicationContext.getBean()获取
  • 可以被其他Bean正常依赖
  • 所有代理都已经生成

七、销毁阶段:Bean的"临终关怀"

销毁方法执行顺序

Spring 容器中 Bean 的销毁过程是一个与初始化相对应的反向流程,同样遵循严格的执行顺序。优先级从高到低:

  1. DestructionAwareBeanPostProcessor 前置处理
public interface DestructionAwareBeanPostProcessor extends BeanPostProcessor {void postProcessBeforeDestruction(Object bean, String beanName);
}
  1. @PreDestroy注解方法(JSR-250标准)
  • 最先执行的销毁逻辑
  • 适用于任何Spring管理的Bean
  • 方法可见性不限(private也可)
@Service
public class OrderService {@PreDestroyprivate void cleanup() {System.out.println("1. @PreDestroy方法执行");}
}
  1. DisposableBean接口实现
  • Spring 原生接口
  • 允许抛出检查异常
  • 在 @PreDestroy之后执行
public interface DisposableBean {void destroy() throws Exception;
}
  1. 自定义destroy-method

配置方式:

<bean class="com.example.DataSource" destroy-method="shutdown"/>

@Bean(destroyMethod = "cleanup")public DataSource dataSource() {return new HikariDataSource();
}

执行特点:

  • 最后执行的销毁逻辑
  • 方法名自由定义
  • 适用于 XML 和 Java 配置

何时触发销毁?

  • 对于单例Bean:在ApplicationContext.close()时
  • 对于原型Bean:需要手动调用destroy方法
  • 对于request/session作用域:在作用域结束时

八、特殊场景处理

1. 循环依赖的三级缓存

Spring通过三级缓存解决循环依赖:

  1. singletonFactories(三级)
  2. earlySingletonObjects(二级)
  3. singletonObjects(一级)

我们可以通过时序图来详细了解Spring解决循环依赖的详细过程:
Spring循环依赖问题解决.png

2. FactoryBean的特殊处理

@Component
public class MyFactoryBean implements FactoryBean<MyProduct> {@Overridepublic MyProduct getObject() {return new MyProduct();}@Overridepublic Class<?> getObjectType() {return MyProduct.class;}
}

获取方式:

  • 获取FactoryBean本身:名称前加"&“(如”&myFactoryBean")
  • 获取产品对象:直接使用bean名称

3. 原型Bean的特殊性

  • 每次getBean()都走完整生命周期
  • 容器不管理原型Bean的销毁

总结:完整的生命周期流程图

SpringBean.png

掌握Spring Bean的完整生命周期,能够帮助您:

  1. 更高效地排查Bean创建问题
  2. 合理使用扩展点增强框架能力
  3. 编写更优雅的Spring组件
  4. 深入理解Spring的设计思想

希望本文对您深入了解 Spring Bean生命周期有所帮助,如果您觉得写的还不错,麻烦点个支持,最新更新会第一时间同步在我的个人公众号【程序员Null自我修养】,喜欢可以点个关注支持哦!

http://www.lryc.cn/news/584970.html

相关文章:

  • 英文国际期刊推荐:MEDS Chinese Medicine,中医药方向可发
  • 47-RK3588 用瑞芯微官方提供recovery进行OTA升级
  • Auto-GPT 简易教程
  • 前端抓包(不启动前端项目就能进行后端调试)--whistle
  • UI前端与数字孪生融合新领域:智慧环保的垃圾分类与回收系统
  • Windos服务器升级MySQL版本
  • 中国银联豪掷1亿采购海光C86架构服务器
  • 如何查看自己本地的公网IP地址?内网环境网络如何开通服务器公网ip提供互联网访问?
  • 电力分析仪的“双语对话”:CCLinkIE与Modbus TCP的无缝连接
  • 从《哪吒 2》看个人IP的破局之道|创客匠人
  • 【实用IP查询工具】IP数据云-IP地址查询离线库使用方案
  • 服务器机柜与网络机柜各自的优势
  • 解决Linux绑定失败地址已使用(端口被占用)的问题
  • python的卷烟营销数据统计分析系统
  • AIStarter新版重磅来袭!永久订阅限时福利抢先看
  • Spring Cloud Gateway介绍 - -基础概念,简单工作原理和配置示例
  • Element Plus和Ant Design Vue深度对比分析与选型指南
  • 飞算 JavaAI:开启 Java 开发新时代
  • C++——构造函数的补充:初始化列表
  • TypeScript---泛型
  • WD0407 40V 7A 超级肖特基二极管,应用于开关汽车工业控制
  • 企业级配置:Azure 邮件与 Cloudflare 域名解析的安全验证落地详解
  • 大数据在UI前端的应用深化:用户行为数据的跨渠道整合分析
  • 拼数(字符串排序)
  • AI产品经理面试宝典第1天:机器学习核心算法全景解析
  • Java结构型模式---组合模式
  • leetcode:518. 零钱兑换 II[完全背包]
  • BPE(Byte Pair Encoding)分词算法
  • leetcode:322. 零钱兑换[完全背包]
  • ARMv9架构