在Spring框架中,Bean的生命周期是其核心机制之一。理解这一流程,不仅能帮助我们更好地使用Spring,还能在需要时通过其提供的丰富扩展点进行定制。本文将采用一种易于理解的方式,系统梳理Spring Bean从诞生到销毁的完整旅程。
第一阶段:Bean定义与实例化
Spring IoC容器启动时,会首先加载配置信息(如XML、Java Config或注解扫描)。这些配置信息被解析并封装为一个个 BeanDefinition 对象。你可以将其理解为一份“建造蓝图”,它定义了Bean的元数据:类名、作用域(单例/原型)、是否懒加载、初始化与销毁方法等,但此时Bean对象本身并未创建。
接下来进入实例化阶段。容器根据BeanDefinition提供的信息,通过反射调用构造方法,创建出Bean的原始对象。此时对象如同一个“空壳”,属性均为默认值,依赖也未注入。
关键扩展点:InstantiationAwareBeanPostProcessor
在此阶段,一个特殊的后置处理器——InstantiationAwareBeanPostProcessor——拥有“偷梁换柱”的能力。它可以在目标Bean实例化之前和之后进行干预。其postProcessBeforeInstantiation方法甚至可以返回一个代理对象,从而完全绕过Spring默认的实例化流程。若它返回了一个非空对象,则后续的依赖注入等标准流程将不会在该对象上执行。
第二阶段:依赖注入与Aware回调
实例化后,容器开始进行依赖注入。容器会查找对象中需要注入的字段或方法(通过@Autowired、@Resource或XML配置),并从容器自身或其他位置获取对应的依赖对象,然后进行注入。至此,Bean对象的基本依赖关系已建立。
接着,如果Bean实现了各种 Aware 接口,容器会进行回调,使Bean能感知到容器的特定资源:
BeanNameAware: 告知Bean自己在容器中的名称(id)。
BeanFactoryAware: 传入当前的BeanFactory实例。
ApplicationContextAware: 传入当前的ApplicationContext实例(功能更丰富)。
- 其他如
EnvironmentAware、ResourceLoaderAware等。
通过这些回调,Bean从被动的被管理对象,转变为可以主动与容器环境交互的组件。
第三阶段:初始化
这是Bean生命周期中最复杂、扩展点最多的阶段。
1. BeanPostProcessor前置处理
所有实现了BeanPostProcessor接口的处理器会执行其postProcessBeforeInitialization方法。此时可以对Bean进行最终的修改或包装。这是一个通用的、强大的扩展点。
2. 初始化方法执行
Spring按顺序执行三种初始化方法:
- 使用
@PostConstruct注解的方法:这是JSR-250标准注解,推荐使用。
- 实现
InitializingBean接口的afterPropertiesSet()方法:Spring原生接口。
- 自定义的
init-method:通过XML的init-method属性或@Bean(initMethod="...")指定。
3. BeanPostProcessor后置处理
接着,BeanPostProcessor的postProcessAfterInitialization方法被调用。这是创建代理对象的黄金时机。我们熟知的Spring AOP动态代理就是在此处生成的。经过这一步,返回的对象可能已经是原始Bean的代理对象,它将负责拦截方法调用,实施事务管理、日志等切面逻辑。
第四阶段:使用与销毁
完成初始化后,Bean就进入了“就绪”状态,被放入单例池(如果是单例作用域),供应用程序使用。
当Spring容器(通常是ApplicationContext)被关闭时,它会开始Bean的销毁流程,顺序与初始化相反:
- 使用
@PreDestroy注解的方法(JSR-250标准)。
- 实现
DisposableBean接口的destroy()方法。
- 自定义的
destroy-method。
在销毁阶段,Bean可以释放占用的资源,如关闭数据库连接池、停止后台线程等。
总结
Spring Bean的生命周期是一个被精心设计的管道流程,涵盖了实例化、属性填充、感知、初始化及销毁等关键环节。框架通过BeanPostProcessor、Aware接口以及各类初始化/销毁方法提供了大量扩展点,使得开发者能够在生命周期的各个阶段插入自定义逻辑,从而实现高度灵活和强大的功能。理解这个生命周期,是深入掌握并高效运用Spring框架的基石。
|