BeanFactory创建流程

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 时序图

在这里插入图片描述

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值