Spring 高级用法和 bean初始化过程
Spring的主要特性和用法
InitializingBean
Spring 容器完成 Bean 的属性注入后,执行该 Bean 的自定义初始化逻辑。
使用场景:
- 框架 / 组件开发中,需要强制子类实现初始化逻辑
- 需要利用 Spring 内部接口的联动机制
例如:某个 Bean 同时实现了 ApplicationContextAware(获取容器上下文)和 InitializingBean,其初始化逻辑依赖容器上下文,而 afterPropertiesSet 的执行时机在 setApplicationContext 之后(Spring 保证 Aware 接口方法先于 afterPropertiesSet 执行)。
如果是业务代码开发,使用init-method即可
DisposableBean
在 Bean 被容器销毁时执行特定的资源清理或收尾操作。
当应用收到关闭信号(如 kill -15 或 Ctrl+C)并进入优雅停机流程时:
内嵌 Web 容器(如 Tomcat、Netty)首先停止接收新请求
容器会等待预设的超时时间(默认 30 秒,可通过 spring.lifecycle.timeout-per-shutdown-phase 配置),让已进入应用的请求继续处理。
若超时前所有请求处理完成,容器正常关闭。
若超时后仍有未完成的请求,容器会强制中断这些请求(避免无限等待)。
SEATA客户端的关闭做的事情例子
与 TC(事务协调器)的通信:TM/RM 会与 TC 维持网络连接(如 Netty 长连接),并上报事务状态(如分支事务注册、全局事务提交 / 回滚)。如果不主动销毁:JVM 突然退出时,TC 可能无法收到「事务中断」的通知,导致 TC 中残留「悬挂的全局事务」(认为事务仍在进行中),进而占用 TC 的资源(如锁、事务日志),甚至影响其他分布式事务的正常执行。
与数据库的交互:RM 会管理本地数据库的分支事务,并持有数据库锁(如行锁)。如果不主动释放:JVM 退出时,若本地事务未完成,数据库可能因无法收到「回滚」指令而长期持有锁,导致其他事务被阻塞(例如,某行数据被锁,其他请求无法更新)。
继承 ApplicationContextAware
在自定义框架或者组件使用applicationContext, 比如获取有自定义注解的类
Seata 2.3 源码
private void findBusinessBeanNamesNeededEnhancement() {
{
if (applicationContext instanceof ConfigurableApplicationContext) {
ConfigurableApplicationContext configurableApplicationContext = (ConfigurableApplicationContext) applicationContext;
ConfigurableListableBeanFactory configurableListableBeanFactory = configurableApplicationContext.getBeanFactory();
String[] beanNames = applicationContext.getBeanDefinitionNames();
for (String contextBeanName : beanNames) {
BeanDefinition beanDefinition = configurableListableBeanFactory.getBeanDefinition(contextBeanName);
if (StringUtils.isBlank(beanDefinition.getBeanClassName())) {
continue;
}
if (IGNORE_ENHANCE_CHECK_SET.contains(beanDefinition.getBeanClassName())) {
continue;
}
try {
// get the class by bean definition class name
Class<?> beanClass = Class.forName(beanDefinition.getBeanClassName());
// check if it needs enhancement by the class
IfNeedEnhanceBean ifNeedEnhanceBean = DefaultInterfaceParser.get().parseIfNeedEnhancement(beanClass);
if (!ifNeedEnhanceBean.isIfNeed()) {
continue;
}
if (ifNeedEnhanceBean.getNeedEnhanceEnum().equals(NeedEnhanceEnum.SERVICE_BEAN)) {
// the native bean which dubbo, sofa bean service bean referenced
PropertyValue propertyValue = beanDefinition.getPropertyValues().getPropertyValue("ref");
if (propertyValue == null) {
// the native bean which HSF service bean referenced
propertyValue = beanDefinition.getPropertyValues().getPropertyValue("target");
}
if (propertyValue != null) {
RuntimeBeanReference r = (RuntimeBeanReference) propertyValue.getValue();
if (r != null && StringUtils.isNotBlank(r.getBeanName())) {
NEED_ENHANCE_BEAN_NAME_SET.add(r.getBeanName());
continue;
}
}
// the native bean which local tcc service bean referenced
NEED_ENHANCE_BEAN_NAME_SET.add(contextBeanName);
} else if (ifNeedEnhanceBean.getNeedEnhanceEnum().equals(NeedEnhanceEnum.GLOBAL_TRANSACTIONAL_BEAN)) {
// global transactional bean
NEED_ENHANCE_BEAN_NAME_SET.add(contextBeanName);
}
} catch (ClassNotFoundException e) {
LOGGER.warn("check if need enhance bean error, it can be ignore", e);
}
}
LOGGER.info("The needed enhancement business beans are : {}", NEED_ENHANCE_BEAN_NAME_SET);
}
}
xxx
Spring 以下的功能都是在bean初始化的哪个阶段执行的?
AOP
变量替换,
@Autoware
@EnableAutoConfiguration 注解,其中真正实现自动配置功能的核心实现者 AutoConfigurationImportSelector
@ComponentScan
@Configuration
bean初始化过程
Spring Bean 的初始化流程是一个从配置解析到最终生成可用 Bean 实例的完整生命周期,结合你提到的各项特性,整体流程可分为以下核心步骤:
一、初始化前的准备阶段
1. 容器启动与配置解析
- 触发点:
ApplicationContext初始化时调用refresh()方法,启动整个流程。 - 核心操作:
@ComponentScan生效:通过ComponentScanAnnotationParser解析@ComponentScan注解,扫描指定包路径下的类(如标注@Component、@Service、@Controller的类),将其转化为BeanDefinition注册到容器。@Configuration处理:标注@Configuration的类会被识别为配置类,其内部通过@Bean定义的方法会被解析为BeanDefinition(特殊处理:配置类会被 CGLIB 代理,确保@Bean方法的单例特性)。AutoConfigurationImportSelector作用:在 Spring Boot 中,该类通过selectImports()方法自动导入 META-INF/spring.factories 中配置的自动配置类,这些类会被解析为BeanDefinition并注册(属于自动配置的核心机制)。
二、BeanFactory 预处理阶段
2. 执行 BeanFactoryPostProcessor
- 触发点:
refresh()方法中的invokeBeanFactoryPostProcessors(beanFactory)。 - 核心操作:
- 变量替换:
PropertySourcesPlaceholderConfigurer(内置BeanFactoryPostProcessor)会在此阶段解析配置中的占位符(如${server.port}),从环境变量、配置文件中获取实际值并替换,确保后续注入的是真实值。 - 其他自定义
BeanFactoryPostProcessor可修改BeanDefinition信息(如动态调整属性值、作用域等)。
- 变量替换:
三、Bean 实例化与依赖注入阶段
3. 实例化 Bean(创建原始对象)
- 触发点:
getBean()→doGetBean()→createBean()→doCreateBean()。 - 核心操作:
- 通过反射调用 Bean 的构造方法创建实例(支持有参构造,需解析构造参数依赖)。
- 对于单例 Bean,若存在循环依赖,会提前暴露一个「早期引用」(通过
ObjectFactory),避免循环依赖导致的实例化失败。
4. 属性注入(依赖注入)
- 触发点:
doCreateBean()中的populateBean()方法。 - 核心操作:
@Autowired生效:AutowiredAnnotationBeanPostProcessor(BeanPostProcessor的实现类)会解析@Autowired注解,根据类型或名称从容器中查找匹配的 Bean,注入到当前 Bean 的属性中(支持字段注入、setter 注入、构造器注入)。- 注入的属性值可能是经过「变量替换」后的实际值(如配置文件中的参数)。
四、Bean 初始化阶段
5. 执行 Aware 接口方法
- 触发点:
initializeBean()中的invokeAwareMethods()。 - 核心操作:若 Bean 实现了
BeanNameAware、BeanFactoryAware、ApplicationContextAware等接口,会在此阶段调用对应的方法(如setApplicationContext()),注入容器相关信息。
6. BeanPostProcessor 前置处理
- 触发点:
applyBeanPostProcessorsBeforeInitialization()。 - 核心操作:所有
BeanPostProcessor的postProcessBeforeInitialization()方法被调用,可对 Bean 进行初始化前的增强(如@PostConstruct注解的处理,由CommonAnnotationBeanPostProcessor完成,其执行时机早于afterPropertiesSet())。
7. 执行初始化方法(含 afterPropertiesSet())
- 触发点:
invokeInitMethods()方法。 - 核心操作:
afterPropertiesSet()作用:若 Bean 实现了InitializingBean接口,Spring 会调用该方法。其核心作用是在所有属性注入完成后执行初始化逻辑,例如属性合法性校验(如非空检查)、基于注入属性的资源初始化(如数据库连接创建)、缓存预热等(依赖于属性注入的操作必须在此处执行,而非构造函数)。- 若配置了自定义
init-method(如@Bean(initMethod = "init")),会调用该方法(执行顺序在afterPropertiesSet()之后)。
8. BeanPostProcessor 后置处理(AOP 代理注入)
- 触发点:
applyBeanPostProcessorsAfterInitialization()。 - 核心操作:
- AOP 代理生成:
AnnotationAwareAspectJAutoProxyCreator(BeanPostProcessor的实现类)会在此阶段检查 Bean 是否匹配切面的切入点(Pointcut)。若匹配,会通过 JDK 动态代理(目标类实现接口)或 CGLIB 代理(目标类无接口)创建代理对象,并替换原始 Bean 实例。 - 代理对象会包含切面逻辑(如
@Before、@After通知),后续从容器中获取的 Bean 实际是代理对象。
- AOP 代理生成:
五、初始化完成阶段
9. 注册销毁逻辑与缓存
- 单例 Bean 会被存入
singletonObjects缓存,供后续直接获取。 - 若 Bean 实现了
DisposableBean或配置了destroy-method,会注册销毁回调,在容器关闭时执行。
总结:特性与流程对应关系
| 特性 | 介入阶段 | 核心实现类/机制 |
|---|---|---|
@ComponentScan |
配置解析阶段 | ComponentScanAnnotationParser |
@Configuration |
配置解析阶段 | ConfigurationClassPostProcessor |
AutoConfigurationImportSelector |
配置解析阶段 | 自动导入 META-INF/spring.factories 配置类 |
| 变量替换 | BeanFactory 预处理阶段 | PropertySourcesPlaceholderConfigurer |
@Autowired |
属性注入阶段 | AutowiredAnnotationBeanPostProcessor |
afterPropertiesSet() |
初始化方法执行阶段 | InitializingBean 接口实现 |
| AOP 代理 | Bean 初始化后处理阶段 | AnnotationAwareAspectJAutoProxyCreator |
通过以上流程,Spring 从配置解析到最终生成增强后的 Bean 实例,各特性在不同阶段协同工作,确保 Bean 最终处于可用状态。其中 afterPropertiesSet() 作为初始化阶段的关键节点,专门用于处理依赖属性注入完成后的初始化逻辑,是连接属性注入与最终可用状态的重要桥梁。

浙公网安备 33010602011771号