1:写在前面
在实际工作中,我可能经常写如下的代码:
@Test
public void testBeanDefinitionLoad() {
// 定义资源
ClassPathResource classPathResource = new ClassPathResource("testbeandefinition.xml");
// 定义IOC容器
DefaultListableBeanFactory defaultListableBeanFactory = new DefaultListableBeanFactory();
// 定义bean定义读取器
XmlBeanDefinitionReader xmlBeanDefinitionReader = new XmlBeanDefinitionReader(defaultListableBeanFactory);
// 通过bean定义读取器从资源中读取bean定义
int i = xmlBeanDefinitionReader.loadBeanDefinitions(classPathResource);
System.out.println("bean定义的个数是:" + i);
}
其中使用的配置文件内容如下:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="testBeanDefinitionBean"
class="yudaosourcecode.spring.TestBeanDefinitionBean"></bean>
<bean id="testBeanDefinitionBean1"
class="yudaosourcecode.spring.TestBeanDefinitionBean"></bean>
<!-- 这里引入自己的话会发生org.springframework.beans.factory.BeanDefinitionStoreException异常 -->
<!--<import resource="testbeandefinition.xml"/>-->
</beans>
这段代码是加载配置文件中的bean信息为spring中的BeanDefinition,这是在spring中存储我们定义的bean信息的数据结构,最终生成spring bean也依赖于次数据结构,代码最终运行效果如下:
bean定义的个数是:2
返回的就是我们在配置文件中定义的bean的个数。
2:loadBeanDefinitions
该方法完成从封装有配置文件的资源中加载beandefinition的方法,具体位置如下:
org.springframework.beans.factory.xml.XmlBeanDefinitionReader#loadBeanDefinitions(org.springframework.core.io.Resource)
@Override
public int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException {
// 其中EncodedResource是加了编码的资源,这里可以忽略
return loadBeanDefinitions(new EncodedResource(resource));
}
继续:
org.springframework.beans.factory.xml.XmlBeanDefinitionReader#loadBeanDefinitions(org.springframework.core.io.support.EncodedResource)
public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {
// 断言判断传入的资源部位null
Assert.notNull(encodedResource, "EncodedResource must not be null");
if (logger.isTraceEnabled()) {
logger.trace("Loading XML bean definitions from " + encodedResource);
}
// <2021-02-24 12:21>
// 从threadlocal中获取已经加载的资源
Set<EncodedResource> currentResources = this.resourcesCurrentlyBeingLoaded.get();
// 如果是不存在已经加载的资源则创建,注意这里是
// 使用的HashSet,因为资源不允许重复
if (currentResources == null) {
currentResources = new HashSet<>(4);
// 存储新创建的资源到threadlocal中
this.resourcesCurrentlyBeingLoaded.set(currentResources);
}
// <2021-02-24 12:23>
// 这里如果是set已经存在会返回false,此时代表资源重复
// 直接抛出BeanDefinitionStoreException信息
if (!currentResources.add(encodedResource)) {
throw new BeanDefinitionStoreException(
"Detected cyclic loading of " + encodedResource + " - check your import definitions!");
}
try {
// 获取对应的资源,然后从资源中获取输入流
InputStream inputStream = encodedResource.getResource().getInputStream();
try {
// 封装到InputSource中
InputSource inputSource = new InputSource(inputStream);
// 如果有编码则使用,一般都不指定,所以这里可以忽略
if (encodedResource.getEncoding() != null) {
inputSource.setEncoding(encodedResource.getEncoding());
}
// <2021-02-24 12:27>
// 实现具体加载为BeanDefinition的过程
return doLoadBeanDefinitions(inputSource, encodedResource.getResource());
}
finally {
inputStream.close();
}
}
catch (IOException ex) {
throw new BeanDefinitionStoreException(
"IOException parsing XML document from " + encodedResource.getResource(), ex);
}
finally {
// 删除资源
currentResources.remove(encodedResource);
// 如果删除当前资源后,没有其他资源,则清空threadlocal
if (currentResources.isEmpty()) {
this.resourcesCurrentlyBeingLoaded.remove();
}
}
}