Spring源码解析系列(一)Bean 生命周期全解析

共计 4554 个字符,预计需要花费 12 分钟才能阅读完成。

一、为什么要深入理解 Spring Bean 生命周期?

在日常 Spring 应用开发中,我们习惯性地通过 @Component@Service@Repository 等注解定义 Bean,通过 @Autowired 注入依赖,甚至可以借助 Spring Boot 自动装配毫不费力地构建出完整的业务系统。

但你是否曾遇到过以下问题:

  • 为什么某些 Bean 的属性注入不到?
  • 为什么我注册的 @PostConstruct 方法没有执行?
  • 如何在 Bean 创建前对其实例进行定制?
  • 动态代理 Bean 生成是在什么时候发生的?
  • Bean 的销毁方法为什么没有执行?

这些问题的根源,归结到 对 Spring Bean 生命周期的理解不够深入。Spring 是一个高度扩展性的框架,理解其生命周期,不仅有助于提升故障排查能力,还能为我们构建框架级别组件提供理论支撑。

二、Spring Bean 生命周期总览图

我们先通过一张流程图对整个生命周期有一个总体感知:

Spring源码解析系列(一)Bean 生命周期全解析

从中可以看出,Spring Bean 生命周期贯穿了 Bean 的整个创建、使用到销毁全过程。下面我们将逐个环节做深入解析,并结合源码剖析其执行逻辑。

三、Spring Bean 生命周期各阶段详解与源码解析

1. BeanDefinition 注册阶段(非实例化)

在 Spring 启动过程中,IOC 容器通过 BeanDefinitionReader 读取配置或扫描注解,将类元信息封装为 BeanDefinition 并注册进 BeanFactory。

AbstractApplicationContext.refresh() {
    obtainFreshBeanFactory();
    invokeBeanFactoryPostProcessors();
    registerBeanPostProcessors();
}

其中:

  • BeanDefinition 只是描述信息,尚未创建对象
  • 这是 @ComponentScan@Configuration 等注解生效的阶段;
  • 此时可通过 BeanFactoryPostProcessor 修改 Bean 的定义(如设置默认值、scope 等);

扩展点举例:

@Component
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory factory) {
BeanDefinition bd = factory.getBeanDefinition("myBean");
bd.getPropertyValues().add("name", "overrideName");
}
}

2.实例化阶段(Instantiation)

Spring 通过反射调用构造器创建 Bean 对象,默认使用无参构造器,也支持构造函数注入(自动推断参数)。

源码入口:

AbstractAutowireCapableBeanFactory.createBeanInstance()

关键逻辑:

protected BeanWrapper createBeanInstance(...) {
    // 1. 如果是 FactoryBean,则调用工厂方法
    // 2. 如果有构造函数参数,尝试自动推导匹配
    // 3. 默认使用无参构造函数进行反射创建实例
}

扩展点:

  • 可通过 InstantiationAwareBeanPostProcessor 拦截实例化行为;
  • 如果你需要返回代理对象(比如提前暴露),也可以在此阶段介入

示例代码:

@Component
public class MyInstantiationProcessor implements InstantiationAwareBeanPostProcessor {
    @Override
    public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) {
        if (beanClass == MyService.class) {
            return Proxy.newProxyInstance(...); // 返回代理对象
        }
        return null;
    }
}

3.依赖注入阶段(Populate Bean)

完成对象创建后,Spring 会进行依赖注入,填充所有 @Autowired@Value@Resource 等注解的字段、setter 方法、构造函数。

源码入口:

AbstractAutowireCapableBeanFactory.populateBean()

依赖注入的实现依赖于 AutowiredAnnotationBeanPostProcessor

InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);
metadata.inject(bean, beanName, pvs);

注意事项:

  • 注入在 实例化之后、初始化之前
  • 此阶段执行失败(如 Bean 不存在)将抛出 NoSuchBeanDefinitionException
  • @Autowired(required = false) 可以避免强依赖。

4.Aware 接口回调

Spring 提供了多种 Aware 接口让 Bean 感知容器的上下文环境:

接口 描述
BeanNameAware 注入 Bean 的名称
BeanFactoryAware 注入 BeanFactory
ApplicationContextAware 注入 ApplicationContext
EnvironmentAware 注入当前运行环境

执行逻辑:

invokeAwareMethods(beanName, bean);

调用顺序:

if (bean instanceof BeanNameAware) { bean.setBeanName(beanName); }
if (bean instanceof BeanFactoryAware) { bean.setBeanFactory(this); }
if (bean instanceof ApplicationContextAware) { bean.setApplicationContext(context); }

5.初始化前处理(BeanPostProcessor)

Spring 提供 BeanPostProcessor 接口允许我们在初始化前后对 Bean 做处理或代理。

初始化前处理:

applyBeanPostProcessorsBeforeInitialization()

此方法会遍历所有注册的 BeanPostProcessor 并调用:

Object postProcessBeforeInitialization(Object bean, String beanName);

使用场景:

  • 校验 Bean 属性是否合法;
  • 给 Bean 设置默认值;
  • Bean 属性审计日志。

6.初始化阶段(InitializingBean、@PostConstruct、init-method)

这是 Bean 生命周期中最关键的一步。

Spring 提供了多种初始化回调方式,执行顺序如下:

① @PostConstruct
② InitializingBean.afterPropertiesSet()
③ init-method(配置文件或注解指定)

执行逻辑:

invokeInitMethods(beanName, bean, mbd);

示例:

@Component
public class MyBean implements InitializingBean {
    @PostConstruct
    public void postConstruct() {
        System.out.println("PostConstruct 初始化...");
    }

    @Override
    public void afterPropertiesSet() {
        System.out.println("afterPropertiesSet 初始化...");
    }

    public void initMethod() {
        System.out.println("init-method 初始化...");
    }
}

在 Spring Boot 中,可以通过注解指定 initMethod:

@Bean(initMethod = "initMethod")
public MyBean myBean() {
    return new MyBean();
}

7.初始化后处理(BeanPostProcessor#postProcessAfterInitialization)

此阶段非常重要,AOP 动态代理就在此发生

源码入口:

applyBeanPostProcessorsAfterInitialization()

常见的代理类如:

  • InfrastructureAdvisorAutoProxyCreator
  • AnnotationAwareAspectJAutoProxyCreator

它们会判断当前 Bean 是否命中某个切面,然后通过 JDK / CGLIB 生成代理类。

你也可以实现自己的 BeanPostProcessor,在这里对 Bean 做增强:

@Override
public Object postProcessAfterInitialization(Object bean, String beanName) {
    if (bean instanceof MyService) {
        return ProxyFactory.createProxy(bean); // 返回代理类
    }
    return bean;
}

8.Bean 就绪(进入 IOC 容器)

此时的 Bean:

  • 已完成初始化;
  • 如果启用了 AOP,可能是代理对象;
  • 加入了 Singleton 缓存;
  • 可以被其他 Bean 注入、使用。

你可以通过 ApplicationContext.getBean() 获取此 Bean,或等待外部调用。

9.容器关闭阶段 & Bean 销毁

当 Spring 容器调用 close() 或触发 registerShutdownHook() 时,Spring 会执行销毁流程:

AbstractApplicationContext.close()
-> doClose()
-> destroyBeans()

Spring Boot 中指定 destroyMethod:

@Bean(destroyMethod = "customDestroy")
public MyBean myBean() {
    return new MyBean();
}

四、总结:掌握生命周期的价值

理解 Spring Bean 生命周期并不仅仅是面试的加分项,它在实际开发中能带来多方面收益:

✅ 理解 Bean 的真正生命周期,避免开发中常见误区
✅ 自定义框架组件(如数据审计、通用监控)能力增强
✅ 为 AOP、事务、事件等高级特性提供认知基础
✅ 能基于生命周期开发通用框架级能力,如热更新、延迟加载等

五、关注后续专栏

本文是《Spring 源码解析系列》专栏的第 1 篇,后续将发布:

  • 《@Transactional 源码深度解读与事务传播机制详解》
  • 《Spring AOP 原理与 CGLIB / JDK 动态代理源码分析》

如果本文对你有帮助,欢迎点赞、评论、收藏!我是 李卷卷,专注Java相关知识输出。感谢阅读!

正文完
 0
李卷卷
版权声明:本站原创文章,由 李卷卷 于2023-04-26发表,共计4554字。
转载说明:除特殊说明外本站文章皆由CC-4.0协议发布,转载请注明出处。
评论(没有评论)