IoC 容器是如何启动的详解

IoC (Inversion of Control,控制反转) 容器是 Spring Framework 的核心。它负责创建、配置和管理应用程序中的对象(称为 Bean)。IoC 容器的启动过程可以概括为以下几个主要阶段:

1. 容器实例化:

  • 创建容器实例: 开发的时候我们通常会选择一个具体的 ApplicationContext 实现类来创建容器。常见的实现类有:

    • ClassPathXmlApplicationContext: 从类路径加载 XML 配置文件。
    • FileSystemXmlApplicationContext: 从文件系统加载 XML 配置文件。
    • AnnotationConfigApplicationContext: 基于 Java 注解配置。
    • WebApplicationContext: 用于 Web 应用(通常由 Spring Boot 自动配置)。
    // 使用 XML 配置
    ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
    
    // 使用 Java 注解配置
    ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
    

2. 加载 Bean 定义 (Bean Definition):

  • 读取配置元数据: 容器会读取配置元数据,这些元数据描述了如何创建和配置 Bean。元数据可以来自:

    • XML 配置文件: <bean> 标签定义了 Bean 的类名、属性、依赖关系等。
    • Java 注解: @Component@Service@Repository@Controller@Configuration@Bean 等注解定义了 Bean。
    • Java 配置类: 使用 @Configuration 注解的类,其中使用 @Bean 注解的方法定义了 Bean。
  • 解析配置元数据: 容器会解析这些元数据,并将其转换为内部的 BeanDefinition 对象。BeanDefinition 包含了 Bean 的所有信息,例如:

    • Bean 的类名 (Class Name)。
    • Bean 的作用域 (Scope,如 singleton、prototype)。
    • Bean 的构造函数参数。
    • Bean 的属性值。
    • Bean 的依赖关系 (Dependencies)。
    • Bean 的初始化方法 (Init Method) 和销毁方法 (Destroy Method)。
    • Bean 是否是懒加载 (Lazy Initialization)。
  • 注册 Bean 定义: 解析后的 BeanDefinition 对象会被注册到容器内部的一个 BeanDefinitionRegistry 中(通常是一个 Map)。

3. Bean 的实例化和依赖注入 (Dependency Injection):

  • Bean 的实例化: 容器根据 BeanDefinition 中的信息,通过反射创建 Bean 的实例。

    • 构造函数注入: 通过构造函数注入依赖。
    • Setter 方法注入: 通过 Setter 方法注入依赖。
    • 字段注入: 直接注入到字段 (不推荐)。
  • 依赖注入: 容器会解析 Bean 之间的依赖关系,并将依赖的 Bean 注入到需要它们的 Bean 中。

    • 自动装配 (Autowiring): 容器可以根据类型、名称或限定符 (Qualifier) 自动查找并注入依赖。
    • 手动装配: 开发者可以在 XML 配置或 Java 配置中显式指定依赖关系。
    • 循环依赖的处理:容器检测循环依赖, 对于prototype作用域的bean, 会抛出异常. 对于单例的bean, 可以通过三级缓存解决(后面详细说明).

4. Bean 的后置处理 (Post-Processing):

  • BeanPostProcessor: 容器允许开发者通过实现 BeanPostProcessor 接口来干预 Bean 的实例化过程。BeanPostProcessor 有两个方法:

    • postProcessBeforeInitialization: 在 Bean 的初始化方法(如 @PostConstructInitializingBean.afterPropertiesSet)执行之前调用。
    • postProcessAfterInitialization: 在 Bean 的初始化方法执行之后调用。
  • Aware 接口: 如果 Bean 实现了 Spring 提供的一些 Aware 接口(如 BeanFactoryAwareApplicationContextAwareBeanNameAware),容器会在 Bean 初始化时调用这些接口的方法,将相应的资源注入到 Bean 中。

  • 初始化方法: 如果 Bean 定义了初始化方法(通过 @PostConstruct 注解、InitializingBean.afterPropertiesSet 方法或 XML 配置中的 init-method 属性指定),容器会在依赖注入完成后调用这些方法。

5. 容器就绪:

  • 经过以上步骤,IoC 容器完成了 Bean 的创建、配置、依赖注入和后置处理。
  • 容器进入就绪状态,可以响应来自应用程序的 Bean 请求。
  • 对于单例 Bean (Singleton Scope),容器会一直持有它们的实例,直到容器关闭。
  • 对于原型 Bean (Prototype Scope),容器每次都会创建一个新的实例。

6. 容器关闭 :

  • 当应用关闭, 可以调用ConfigurableApplicationContext接口的close()方法关闭容器.
  • 销毁方法: 如果 Bean 定义了销毁方法(通过 @PreDestroy 注解、DisposableBean.destroy 方法或 XML 配置中的 destroy-method 属性指定),容器会在关闭时调用这些方法,释放 Bean 占用的资源。

循环依赖的处理 (三级缓存):

Spring 使用三级缓存来解决单例 Bean 之间的循环依赖:

  1. 一级缓存 (singletonObjects): 存放完全初始化好的 Bean(成品)。
  2. 二级缓存 (earlySingletonObjects): 存放早期暴露的 Bean(半成品,已实例化但未完成属性注入)。
  3. 三级缓存 (singletonFactories): 存放 Bean 工厂对象 (ObjectFactory),用于创建 Bean 的早期引用。

处理流程:

  1. 当创建 Bean A 时,发现它依赖于 Bean B。
  2. 创建 Bean B 时,发现它依赖于 Bean A。
  3. 此时,Bean A 已实例化(但未完成属性注入),将其对应的 ObjectFactory 放入三级缓存。
  4. Bean B 可以从三级缓存获取 Bean A 的早期引用,完成自身的属性注入。
  5. Bean B 完成初始化后,放入一级缓存。
  6. Bean A 继续完成属性注入(此时可以从一级缓存获取到已完成初始化的 Bean B),然后放入一级缓存。

总结流程图:

                                       +---------------------+
                                       |  1. 容器实例化       |
                                       | (ApplicationContext) |
                                       +---------------------+
                                               |
                                               V
      +-------------------------------------------------------------------------+
      |                         2. 加载 Bean 定义                               |
      |  +-----------------+     +-----------------+     +-------------------+  |
      |  | 读取配置元数据     |---->| 解析配置元数据     |---->| 注册 BeanDefinition |  |
      |  | (XML, Annotations, |     | (转换为            |     | (到 BeanDefinition  |  |
      |  |  Java Config)    |     |  BeanDefinition)  |     |  Registry)        |  |
      |  +-----------------+     +-----------------+     +-------------------+  |
      +-------------------------------------------------------------------------+
                                               |
                                               V
     +-----------------------------------------------------------------------------+
     |                   3. Bean 的实例化和依赖注入                                    |
     |    +----------------+      +----------------+      +---------------------+   |
     |    |   Bean 实例化   |----->|   依赖注入       |----->|     循环依赖处理       |   |
     |    | (反射, 构造函数) |      | (自动装配, 手动) |      | (三级缓存)           |   |
     |    +----------------+      +----------------+      +---------------------+   |
     +-----------------------------------------------------------------------------+
                                               |
                                               V
     +-------------------------------------------------------------------------------+
     |                         4. Bean 的后置处理                                     |
     | +-----------------------+  +----------------+  +------------------------+  |
     | | BeanPostProcessor    |  |   Aware 接口     |  |    初始化方法            |  |
     | | (before/after init)   |  | (注入资源)       |  | (@PostConstruct, init-method) |  |
     | +-----------------------+  +----------------+  +------------------------+  |
     +-------------------------------------------------------------------------------+
                                               |
                                               V
                                       +---------------------+
                                       |     5. 容器就绪       |
                                       +---------------------+
                                               |
                                               V (可选)
                                       +---------------------+
                                       |     6. 容器关闭       |
                                       |   (销毁方法)         |
                                       +---------------------+

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

冰糖心书房

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

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

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

打赏作者

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

抵扣说明:

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

余额充值