spring源码解析(二)obtainFreshBeanFactory方法分析

本文深入剖析了Spring中的obtainFreshBeanFactory方法,详细解释了该方法如何加载和解析配置文件,注册BeanDefinition到BeanFactory的过程,包括配置文件路径获取、Resource处理、XML解析、Document注册等步骤,以及在处理profile属性时的关键操作。
摘要由CSDN通过智能技术生成

小序

obtainFreshBeanFactory方法是spring中一个比较重要的方法,主要是获取一个beanfactory,在

refresh方法的第三个模块,如下:

okay 那么这个方法具体做了哪些事情呢,,,

该方法会解析所有 Spring 配置文件(application-**.xml,通常我们会放在 resources 目录下),将所有 Spring 配置文件中的 bean 定义封装成 BeanDefinition,加载到 BeanFactory 中。常见的,如果解析到<context:component-scan base-package="" /> 注解时,会扫描 base-package 指定的目录,将该目录下使用指定注解(@Controller、@Service、@Component、@Repository)的配置也同样封装成 BeanDefinition,加载到 BeanFactory 中。
上面提到的 “加载到 BeanFactory 中” 的意思主要指的是添加到以下3个缓存:

要注意这个方法只是注册spring自己的注解bean到容器中,,如果有其他扩展需求,比如mybatis组件扫描或者dubbo组件扫描那么可能要自己实现一个beanfactorypostprocessor,然后在spring启动在invokeBeanFactoryPostProcessors这个方法中执行即可

1、 beanDefinitionNames缓存:所有被加载到 BeanFactory 中的 bean 的 beanName 集合。
2、 beanDefinitionMap缓存:所有被加载到 BeanFactory 中的 bean 的 beanName 和 BeanDefinition 映射。
3 、aliasMap缓存:所有被加载到 BeanFactory 中的 bean 的 beanName 和别名映射。

 

正文

首先,我们来到 obtainFreshBeanFactory 方法

1.刷新 BeanFactory,由 AbstractRefreshableApplicationContext 实现,见代码块1详解

 

代码块1:refreshBeanFactory 方法

 

2.加载 bean 定义,由 XmlWebApplicationContext 实现,见代码块2详解

 

代码块2:loadBeanDefinitions

3.加载 bean 定义,见代码块3详解

代码块3:loadBeanDefinitions

这里会做两件事情

第一:获取配置文件路径,若configLocations 属性不为空 则返回configLocations,否则就调用getDefaultConfigLocations()获取默认的配置文件路径,,configLocations是我们在web.xml中配置的contextConfigLocation的值,如下:

如果 web.xml 中没有配置 contextConfigLocation 参数,则会拿到 Spring 默认的配置路径:/WEB-INF/applicationContext.xml

第二,根据配置文件解析配置文件,然后生成beandefinition见代码块4详解

代码块4:loadBeanDefinitions

上图做了两件事情:

1.获取 resourceLoader:这个 resourceLoader 值为 XmlWebApplicationContext。在上文代码块2中会将 resourceLoader 属性值赋为 XmlWebApplicationContext

2.判断 resourceLoader 是否为 ResourcePatternResolver 的实例:这边 resourceLoader  为 XmlWebApplicationContext,而 XmlWebApplicationContext 的继承关系如下图,可以看到是有实现 ResourcePatternResolver 接口的,因此这边判断结果为 true

2.1 根据路径拿到该路径下所有符合的配置文件,并封装成 Resource。如果我们配置的路径为:classpath /*.xml,

并且项目配置如下图,则该方法会拿到2个配置文件:bean.xml 和 core.xml。

2.2 根据 Resource,加载 bean 定义,见代码块5详解

代码块5:loadBeanDefinitions

2.根据 Resource 加载 bean 定义,由 XmlBeanDefinitionReader 实现,见代码块6详解

代码块6:loadBeanDefinitions

 

7.加载 bean 定义,开始正式处理,见代码块7详解

代码块7:doLoadBeanDefinitions

上图的代码会做两件事情:

1.根据 inputSource 和 resource 加载 XML文件,并封装成 Document,见代码块8详解

2.根据返回的 Document 注册 bean 信息,见代码块9详解

代码块8:doLoadDocument

上面的代码块主要是:获取 XML 配置文件的验证模式。XML 文件的验证模式是用来保证 XML 文件的正确性,常见的验证模式有两种:DTD 和 XSD,以下简单展示下这两种验证模式的配置。

DTD 验证模式已经停止更新 如下:

XSD 验证模式

代码块9:registerBeanDefinitions

代码块9 中主要有两个部分:

1.根据 resource 创建一个 XmlReaderContext,见代码块10详解

2.加载及注册 bean 定义,由 DefaultBeanDefinitionDocumentReader 实现,见代码块11详解

代码块10:createReaderContext

 

代码块10中会根据 resource 构建一个 XmlReaderContext,用于存放解析时会用到的一些上下文信息。

其中 namespaceHandlerResolver 会创建默认的 DefaultNamespaceHandlerResolver,DefaultNamespaceHandlerResolver的handlerMappingsLocation 属性会使用默认的值 “META-INF/spring.handlers”,并且这边有个重要的属性 handlerMappings,handlerMappings 用于存放命名空间和该命名空间handler类的映射 如下:

handlerMappings 的值默认位于“META-INF/spring.handlers” 文件下,一般在我们定义自定义注解时需要用到

 

代码块11:registerBeanDefinitions

 

通过拿到的节点,注册 bean 定义,见代码块12详解

上面主要做两件事情:

1 处理 profile 属性,见代码块13详解

2 解析并注册 bean 定义,见代码块14详解

代码块12  处理 profile 属性

profile 属性主要用于多环境开发,例如下图:

我们可以在配置文件中同时写上多套配置来适用于开发环境、测试环境、生产环境,这样可以方便的进行切换开发、部署环境,最常用的就是更换不同的数据库。具体使用哪个环境在 web.xml 中通过参数 spring.profiles.active 来配置。

代码块13:parseBeanDefinitions
 

终于,我们来到了解析 bean 定义的核心部分,这边会遍历 root 节点(正常为 <beans> 节点)下的所有子节点,对子节点进行解析处理。

如果节点的命名空间是 Spring 默认的命名空间,则走 parseDefaultElement(ele, delegate) 方法进行解析,例如最常见的:<bean></bean>

如果节点的命名空间不是 Spring 默认的命名空间,也就是自定义命名空间,则走 delegate.parseCustomElement(ele) 方法进行解析,例如常见的: <context:component-scan/>和<aop:aspectj-autoproxy/>

 

parseDefaultElement(ele, delegate) 和 delegate.parseCustomElement(ele) 方法是解析 bean 定义的两个核心方法

具体需要后面再介绍。。。。

默认命名空间类似:http://www.springframework.org/schema/beans 如下:

自定义命名空间类似http://www.springframework.org/schema/aop 如下图:

 

 

画重点:

okk,本文主要介绍了加载 bean 定义的一些基本工作:

创建一个新的 BeanFactory:DefaultListableBeanFactory。
根据 web.xml 中 contextConfigLocation 配置的路径,读取 Spring 配置文件,验证配置文件的内容,并封装成 Resource。
根据 Resource 加载 XML 配置文件,并解析成 Document 对象 。
拿到 Document 中的根节点,遍历根节点和所有子节点。

后面的解析默认命名空间和自定义命名空间的部分是核心部分,,,需要详细解析。。。后面继续更新。。
 


 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值