ApplicationContext 如何创建 Bean 实例?

ApplicationContext 创建 Bean 实例的过程主要在其内部的 BeanFactory 中进行,通常是在 AbstractBeanFactorydoGetBean 方法中,以及 DefaultListableBeanFactorypreInstantiateSingletons 方法(用于预实例化非懒加载的单例 Bean)中。

以下是创建 Bean 实例的详细步骤:

1. 获取 Bean 定义 (Get BeanDefinition):

  • BeanDefinitionRegistry (通常是 DefaultListableBeanFactory 内部的 Map) 中根据 Bean 的名称获取对应的 BeanDefinition 对象。

2. 检查是否已创建 (Check if already created):

  • 单例 Bean (Singleton): 检查该 Bean 是否已经创建并缓存。如果是,直接返回缓存的实例。
  • 原型 Bean (Prototype): 每次请求都会创建新的实例。
  • 其他作用域 (Request, Session, etc.): 根据具体的作用域规则进行检查。

3. 处理 depends-on (Handle depends-on):

  • 如果该 Bean 定义了 depends-on 属性(依赖于其他 Bean),则先创建并初始化它所依赖的 Bean。

4. 创建 Bean 实例 (Create Bean Instance):

  • 选择创建方式:

    • 普通 Bean: 通过构造函数、工厂方法或 FactoryBean 创建。
    • FactoryBean: 如果 Bean 是一个 FactoryBean,则调用其 getObject() 方法来获取实际的 Bean 实例。
    • 工厂方法 (Factory Method): 如果 Bean 定义指定了工厂方法,则调用该工厂方法来创建 Bean 实例。静态工厂方法或者实例工厂方法.
    • 构造函数 (Constructor): 如果没有指定工厂方法,则使用构造函数创建 Bean 实例。
      • 无参构造函数: 如果没有指定构造函数参数,则使用无参构造函数。
      • 有参构造函数: 如果指定了构造函数参数,则使用匹配的构造函数。
        • 自动装配构造函数参数: 根据类型或名称自动解析构造函数参数。
        • 手动指定构造函数参数: 在 XML 配置或 Java 配置中显式指定构造函数参数。
  • 实例化:

    • 通常通过反射(Constructor.newInstance())调用构造方法或工厂方法来创建 Bean 实例。
    • InstantiationAwareBeanPostProcessor: 在 Bean 实例化前后,会调用 InstantiationAwareBeanPostProcessorpostProcessBeforeInstantiationpostProcessAfterInstantiation 方法,允许对实例化过程进行干预(例如,返回一个代理对象)。

5. 属性填充 (Populate Bean):

  • 将 Bean 定义中指定的属性值设置到 Bean 实例中。
  • 注入方式:
    • Setter 注入: 调用 Bean 的 Setter 方法。
    • 字段注入: 直接设置 Bean 的字段值(不推荐)。
  • 属性解析:
    • 字面量值: 直接设置字符串、数字等字面量值。
    • 引用其他 Bean: 根据 Bean 的名称或类型,从容器中获取依赖的 Bean,并注入。
    • 集合、数组、Map: 解析配置中的集合、数组、Map 元素,并注入。
    • SpEL 表达式: 解析 SpEL 表达式,并将结果注入。
    • 自动装配: 根据类型、名称或 @Qualifier 自动查找并注入依赖。
  • 类型转换: 如果属性的类型与配置值的类型不匹配,Spring 会尝试进行类型转换(使用 TypeConverterConversionService)。
  • InstantiationAwareBeanPostProcessor.postProcessProperties/postProcessPropertyValues:
    • 在属性设置期间, 会调用 InstantiationAwareBeanPostProcessorpostProcessProperties (或 postProcessPropertyValues,已弃用) 方法。
    • 允许对属性值进行修改或执行其他操作。
    • 典型的应用:处理 @Autowired@Value@Resource 等注解。

6. Aware 接口回调:

  • 如果 Bean 实现了 Spring 提供的一些 Aware 接口(如 BeanNameAwareBeanFactoryAwareApplicationContextAware 等),容器会在属性注入完成后、初始化之前调用这些接口的方法,将相应的资源注入到 Bean 中。

7. 初始化 (Initialization):

  • BeanPostProcessor 前置处理:

    • 调用所有已注册的 BeanPostProcessorpostProcessBeforeInitialization 方法。
    • 允许在 Bean 初始化之前对 Bean 进行修改或执行其他操作。
  • 调用初始化方法:

    • InitializingBean 接口: 如果 Bean 实现了 InitializingBean 接口,则调用其 afterPropertiesSet 方法。
    • @PostConstruct 注解: 如果 Bean 的方法上有 @PostConstruct 注解,则调用该方法。
    • init-method 属性: 如果 Bean 定义中指定了 init-method 属性,则调用指定的方法。
  • BeanPostProcessor 后置处理:

    • 调用所有已注册的 BeanPostProcessorpostProcessAfterInitialization 方法。
    • 允许在 Bean 初始化之后对 Bean 进行修改或执行其他操作(例如,创建代理对象)。

8. 注册一次性 Bean (Register Disposable Bean):

  • 如果 Bean 实现了 DisposableBean 接口,或者定义了销毁方法(@PreDestroy 注解或 destroy-method 属性),则将该 Bean 注册为一次性 Bean,以便在容器关闭时销毁。

9. 完成 (Completion):

  • 对于单例 Bean,将创建好的 Bean 实例放入单例缓存中。
  • 对于原型 Bean,将创建好的 Bean 实例返回给调用者。

循环依赖的处理:

  • 对于单例Bean的循环依赖,Spring使用三级缓存来解决。
  • 对于prototype Bean的循环依赖, Spring无法解决, 会抛出异常.

总结流程图:

+-----------------------+
|    getBean(name)     |  (获取 Bean)
+-----------------------+
        |
        V
+-----------------------+
|  Get BeanDefinition   |  (获取 Bean 定义)
+-----------------------+
        |
        V
+-----------------------+
| Check if created      |  (检查是否已创建)
+-----------------------+
        |
        V
+-----------------------+
| Handle depends-on     |  (处理 depends-on)
+-----------------------+
        |
        V
+-----------------------+
| Create Bean Instance  |  (创建 Bean 实例)
+-----------------------+
        |
        |  - FactoryBean?
        |  - Factory Method?
        |  - Constructor (无参/有参, 自动装配/手动指定)
        |  - InstantiationAwareBeanPostProcessor (before/after)
        |
        V
+-----------------------+
|   Populate Bean       |  (属性填充)
+-----------------------+
        |
        |  - Setter 注入 / 字段注入
        |  - 字面量值 / 引用其他 Bean / 集合 / SpEL
        |  - 类型转换
        |  - InstantiationAwareBeanPostProcessor.postProcessProperties
        |
        V
 +----------------------+
 |  Aware接口回调       |
 +----------------------+
        |
        V
+-----------------------+
|   Initialization      |  (初始化)
+-----------------------+
        |
        |  - BeanPostProcessor (before)
        |  - InitializingBean.afterPropertiesSet
        |  - @PostConstruct
        |  - init-method
        |  - BeanPostProcessor (after)
        |
        V
+-----------------------+
|Register DisposableBean| (注册一次性 Bean)
+-----------------------+
        |
        V
+-----------------------+
|       Return Bean     |  (返回 Bean 实例)
+-----------------------+

关键点:

  • BeanFactory 负责创建 Bean 实例,ApplicationContext 提供了更高级的功能(如事件、国际化等)。
  • BeanDefinition 描述了如何创建和配置 Bean。
  • InstantiationAwareBeanPostProcessor 可以在 Bean 实例化前后进行干预。
  • BeanPostProcessor 可以在 Bean 初始化前后进行处理。
  • Spring 支持多种注入方式(构造函数注入、Setter 注入、字段注入)。
  • Spring 会自动处理类型转换。
  • Spring 通过三级缓存解决单例Bean的循环依赖.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

冰糖心书房

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值