BeanFactory创建流程

本文详细解析了Spring IoC容器中BeanFactory的获取与初始化过程,包括`obtainFreshBeanFactory`方法的执行,以及BeanDefinition的加载、解析和注册核心步骤。重点剖析了`DefaultListableBeanFactory`的创建和BeanDefinition的注册机制,为读者揭示了Spring IoC的核心工作原理。

1. 获取BeanFactory

在SpringIOC容器创建的主流程中,第二步就是获取一个BeanFactory对象,详情可见如下方法 org.springframework.context.support.AbstractApplicationContext#refresh,入口如下:

ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

进入**obtainFreshBeanFactory()**方法,看到如下内容:

protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
   // 1. 初始化BeanFactory对象
   refreshBeanFactory();
   // 2. 返回BeanFactory对象
   return getBeanFactory();
}

第一步: 初始化BeanFactory对象: **refreshBeanFactory()**方法
org.springframework.context.support.AbstractRefreshableApplicationContext#refreshBeanFactory

@Override
protected final void refreshBeanFactory() throws BeansException {
   //判断是否已有beanFactory
   if (hasBeanFactory()) {
      //销毁beans
      destroyBeans();
      //关闭beanFactory
      closeBeanFactory();
   }
   try {
      //实例化DefaultListableBeanFactory
      DefaultListableBeanFactory beanFactory = createBeanFactory();
      //设置序列化ID
      beanFactory.setSerializationId(getId());
      //自定义bean工厂的一些属性(是否覆盖,是否循环依赖)
      customizeBeanFactory(beanFactory);
      //加载应用中的BeanDefinitions
      loadBeanDefinitions(beanFactory);
      synchronized (this.beanFactoryMonitor) {
         //赋值当前bean工厂
         this.beanFactory = beanFactory;
      }
   }
   catch (IOException ex) {
      throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
   }
}

创建BeanFactory,很显然进到createBeanFactory方法中,

protected DefaultListableBeanFactory createBeanFactory() {
   return new DefaultListableBeanFactory(getInternalParentBeanFactory());
}

通过上图可以清晰得看到,BeanFactory是一个顶级的接口,那么在实例化过程中,默认的实现就是DefaultListableBeanFactory对象。
第二步:返回BeanFactory对象:getBeanFactory()方法
org.springframework.context.support.AbstractRefreshableApplicationContext#getBeanFactory

@Override
public final ConfigurableListableBeanFactory getBeanFactory() {
   synchronized (this.beanFactoryMonitor) {
      if (this.beanFactory == null) {
         throw new IllegalStateException("BeanFactory not initialized or already closed - " +
               "call 'refresh' before accessing beans via the ApplicationContext");
      }
      return this.beanFactory;
   }
}

从上述代码可看出,第二步也就是返回了第一步初始化的BeanFactory的实例化对象。
时序图:
在这里插入图片描述

2. BeanDefinition加载解析及注册子流程

2.1 关键步骤

1.Resource定位: 指对BeanDefinition资源的定位过程,也就是找到定义Java Bean的XML文件,并将其中的定义的Bean封装成BeanDefinition对象。
2.BeanDefinition载入: 将XML中定义的Bean封装成的BeanDefinition对象注册到Spring IOC容器中,方便注入和调用。

2.2 Resource定位

step-1. 流程入口

⼦流程⼊⼝在 AbstractRefreshableApplicationContext#refreshBeanFactory
在这里插入图片描述

step-2. 加载Resource文件和解析

依次调⽤多个类的 loadBeanDefinitions ⽅法 ​ —> AbstractXmlApplicationContext ​ —>
AbstractBeanDefinitionReader —> XmlBeanDefinitionReader ​ ⼀直执⾏到
XmlBeanDefinitionReader 的 doLoadBeanDefinitions ⽅法
在这里插入图片描述
我们重点观察XmlBeanDefinitionReader 类的 registerBeanDefinitions ⽅法,期间产⽣了多次重载调⽤,我们定位到最后⼀个
在这里插入图片描述
关注1的createReaderContext方法:
在这里插入图片描述
在这里插入图片描述
此处Spring首先完成了NamespaceHandlerResolver的初始化。
关注2的documentReader.registerBeanDefinitions方法,调用了DefaultBeanDefinitionDocumentReader#registerBeanDefinitions ⽅法
在这里插入图片描述
进入doRegisterBeanDefinitions方法:
在这里插入图片描述
进入parseBeanDefinitions方法:
在这里插入图片描述
进入到parseDefaultElement方法:
在这里插入图片描述
进入processBeanDefinition方法:
在这里插入图片描述
⾄此,Resource文件定位和解析过程结束,我们发现,所谓的注册就是把封装的 XML 中定义的 Bean信息解析成了一个BeanDefinitionsHolder对象。

2.3 BeanDefinition载入

在上一节中已经将XML文件中定义的Bean封装成了BeanDefinitionsHolder对象,接下来就是将BeanDefinition注册到IOC容器中,主要调用的就是:
org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader#processBeanDefinition方法:
在这里插入图片描述
进入到BeanDefinitionReaderUtils.registerBeanDefinition方法中,
在这里插入图片描述
进入registry.registerBeanDefinition方法中,就进入到了org.springframework.beans.factory.support.DefaultListableBeanFactory#registerBeanDefinition方法,
在这里插入图片描述
⾄此,注册流程结束,我们发现,所谓的注册就是把封装的 XML 中定义的 Bean信息封装为BeanDefinition 对象之后放⼊⼀个Map中。

2.4 时序图

在这里插入图片描述

### Bean 创建流程的核心步骤 Spring Boot 中 Bean 的创建流程Spring 容器的核心机制之一,涉及多个阶段的协同工作。整个流程从上下文准备到单例 Bean 的实例化,涵盖了 Bean 定义的加载、修改、实例化以及初始化等多个步骤。 #### Bean 定义的加载与注册 Spring Boot 启动时,会根据主类的包扫描路径加载所有带有注解(如 `@Component`、`@Service`、`@Repository`、`@Configuration`)的类,并将这些类解析为 `BeanDefinition` 对象,注册到 `ApplicationContext` 中。`BeanDefinition` 包含了 Bean 的名称、类型、作用域、构造函数参数、依赖关系等元数据信息[^3]。 ```java @Configuration public class MyConfiguration { @Bean public MyService myService() { return new MyServiceImpl(); } } ``` #### Bean 定义的修改 在 Bean 定义加载完成后,Spring 容器会调用 `BeanFactoryPostProcessor` 对 `BeanDefinition` 进行修改。`BeanDefinitionRegistryPostProcessor` 是 `BeanFactoryPostProcessor` 的子类,它提供了对 `BeanDefinitionRegistry` 的后置处理能力,允许开发者动态添加或修改 Bean 定义[^5]。 例如,可以通过实现 `BeanFactoryPostProcessor` 接口来修改 Bean 的配置: ```java @Component public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor { @Override public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { // 修改 Bean 的定义 } } ``` #### Bean 的创建 Spring Boot 的 Bean 创建流程可以分为多个阶段,具体包括以下几个关键步骤: 1. **特殊 Bean 的创建** 在 `prepareContext` 阶段,Spring创建一些特殊的 Bean,如 `BeanFactoryPostProcessor` 和 `BeanPostProcessor`。这些 Bean 在容器初始化过程中具有重要作用,例如用于修改 Bean 定义或处理 Bean 的生命周期[^4]。 2. **普通 Bean 的创建** 在 `preInstantiateSingletons` 方法中,Spring 会实例化所有非懒加载的单例 Bean。懒加载的 Bean(通过 `@Lazy` 注解标记)不会在此阶段创建,而是等到首次被请求时才进行实例化[^4]。 3. **递归创建依赖 Bean** 在 Bean 的创建过程中,如果某个 Bean 依赖于其他 Bean,Spring 会递归地创建这些依赖 Bean。例如,如果 `MyService` 依赖于 `MyRepository`,则在创建 `MyService` 时会先创建 `MyRepository`。 #### Bean 的实例化与初始化 在 Bean 的创建过程中,Spring 会执行以下关键步骤: 1. **实例化 Bean** Spring 通过反射调用 Bean 的构造函数或工厂方法来创建 Bean 实例。此阶段会生成一个未完全初始化的 Bean 对象[^4]。 2. **属性注入** Spring 会为 Bean 注入依赖的属性值。这些属性可以是通过 `@Autowired` 或 `@Value` 注解标记的字段[^4]。 3. **BeanPostProcessor 处理** 在 Bean 的初始化过程中,Spring 会调用 `BeanPostProcessor` 接口的方法,允许开发者对 Bean 进行自定义处理。例如,可以通过 `BeanPostProcessor` 修改 Bean 的属性值或替换 Bean 的实现[^4]。 4. **初始化方法调用** 如果 Bean 实现了 `InitializingBean` 接口或定义了自定义的初始化方法(通过 `@PostConstruct` 注解),Spring 会在 Bean 完成属性注入后调用这些初始化方法[^4]。 5. **注册销毁方法** 如果 Bean 实现了 `DisposableBean` 接口或定义了自定义的销毁方法(通过 `@PreDestroy` 注解),Spring 会在 Bean 被销毁时调用这些方法,用于释放资源[^4]。 #### 循环依赖的处理 Spring 通过三级缓存机制解决循环依赖问题。在 Bean 的创建过程中,未完全初始化的 Bean 会被暂时存储在缓存中,以避免循环依赖导致的无限递归问题。具体来说,Spring 使用 `SingletonFactory` 来生成 Bean 的早期引用,并将其存储在缓存中,以便在依赖注入时能够正确解析循环依赖[^4]。 ### Bean 创建流程的扩展点 Spring Boot 提供了多个扩展点,开发者可以通过实现特定的接口或注解来干预 Bean 的创建流程。例如: - **BeanFactoryPostProcessor**:用于修改 Bean 定义。 - **BeanPostProcessor**:用于修改 Bean 的属性或替换 Bean 的实现。 - **@PostConstruct** 和 **@PreDestroy**:用于定义 Bean 的初始化和销毁逻辑。 - **@Lazy**:用于控制 Bean 的懒加载行为。 这些扩展点使得开发者能够灵活地控制 Bean 的生命周期和行为,从而满足特定的业务需求。 ### 相关问题 1. Spring Boot 中的自动配置是如何影响 Bean 的创建流程的? 2. 如何通过 `BeanPostProcessor` 修改 Bean 的属性? 3. `@PostConstruct` 和 `@PreDestroy` 在 Bean 的生命周期中分别起到什么作用? 4. Spring 是如何解决循环依赖问题的? 5. `@Lazy` 注解在 Bean 创建流程中的作用是什么?
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值