梳理 Spring Bean 的生命周期

Spring对Bean生命周期的管理不仅有效地管理了Bean之间的依赖关系,还为开发者提供了丰富的扩展点。本文将从Spring容器启动开始,从储存Bean定义到注册销毁Bean,完整地梳理Bean的生命周期,深入体会Bean实例创建的灵活性与可靠性。

pre: Spring 如何知道要创建哪些 Bean 呢?

在Spring容器启动后,启动 loadBeanDefinitions() 方法,通过配置文件、注解扫描等方式找到程序员在代码中定义的Bean类,将Bean的定义信息注册到spring容器中。

Spring会将这些类定义信息转换为 BeanDefinition 对象并存储到 BeanDefinitionRegistry 中。

有了需要生成的bean定义的集合,后续就可以遍历这个集合,用类定义信息逐个调用 doCreateBean() 方法创建Bean。

⚠️注意:BeanFactoryPostProcessor Bean工厂后处理器 就是在 BeanDefinitionMap 填充完毕,Bean实例化之前执行的。可以让开发者对BeanDefinition进行动态修改。

创建 Bean 的流程

创建Bean的流程大致分为四个阶段:

  • 对象实例化
  • 属性填充
  • 实例初始化
  • 注册销毁

在方法doCreateBean()中很清晰的依次执行了这四个步骤

// AbstractAutowireCapableBeanFactory.java 简化版
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
    throws BeanCreationException {

    // 1. 对象实例化
    BeanWrapper instanceWrapper = null;
    if (instanceWrapper == null) {
        instanceWrapper = createBeanInstance(beanName, mbd, args);
    }

    Object bean = instanceWrapper.getWrappedInstance();
    // 
    Object exposedObject = bean;

    try {
        // 2. 属性填充
        populateBean(beanName, mbd, instanceWrapper);
        // 3. 实例初始化
        exposedObject = initializeBean(beanName, exposedObject, mbd);
    }

    // 4. 注册销毁回调接口
    try {
        this.registerDisposableBeanIfNecessary(beanName, bean, mbd);
        return exposedObject;
    }
}

下面对这四个阶段逐一介绍:

1 对象实例化 / 构造对象

通过调用 createBeanInstance() ,进行Bean实例构造。

a 利用反射机制从Bean定义中拿到该类的构造方法。具体拿哪个构造方法的规则:

  • 有多个构造方法时,拿加了@Autowired的构造方法;
  • 如果有多个构造方法加了@Autowired注解,不能判断报错;
  • 如果都没加注解,优先拿无入参的方法,全部都有入参,spring回根据参数的类型来尝试匹配。

b 在调用构造方法时,Spring会根据参数的类型在容器中查找对应的依赖,支持基于类型或名称的依赖查找,必要时使用@Qualifier等注解进行细化。

c 有了构造函数和对应入参,通过反射进行Bean的构造


用类中唯一的构造方法来进行Bean的注入的优势也体现在这里: 明确的依赖关系

使用类中唯一的构造方法进行Bean注入,可以确保依赖关系在实例化时明确无误。构造函数的参数直接表明了该类所依赖的其他Bean,这种强制性有助于防止依赖未被满足的情况。


2 属性填充

通过调用 populateBean() ,对Bean内部需要的属性进行填充,通常来说就是加了@Autowired注解的变量。通过三级缓存机制进行填充,从而避免循环依赖。


3 实例初始化

经过对象实例化和属性填充后,Bean的依赖已经被解析并注入,但此时Bean还没有完成其全部的初始化过程,因此还不具备Spring要求的完整生命周期特性,不能被直接添加到单例池中。

这一部分的目的是确保Bean在spring容器中被完全初始化,准备好在应用程序中使用,同时运行开发者对Bean进行功能扩展。调用 initializeBean()来完成。具体来说,可以分为下面几部分:

1 检查 Aware 相关接口并设置相关依赖(容器信息);

2 执行BeanPostProcessor类后处理器中设置的前置类后处理器方法(如果有的话);

类后处理器是Spring提供的重要扩展点,允许用户介入到Bean的实例化流程中。

3 调用invokeInitMethods(),若 Bean 实现了 InitializingBean 接口,调用 afterPropertiesSet() 方法

4 执行自定义的初始化方法 init-method()

5 执行BeanPostProcessor类后处理器中设置的后置类后处理器方法(如果有的话);

到这里为止,就已经完成了Bean实例的完全初始化,可以被正常使用了。


4 注册销毁

为了确保Bean实例能够被优雅地销毁,在将Bean放入单例池之前,会调用 registerDisposableBeanIfNecessary() 方法注册实现了 DisposableBean 接口的Bean。这样,在需要销毁该Bean时,可以调用其 destroy() 方法来实现销毁逻辑。


通过这几个步骤,完整的Bean就被创建并准备好使用。最后,通过 addSingleton() 方法将这个Bean添加到单例池中,以便后续使用管理。

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇