前文
在之前介绍了资源与工厂创建流程解析,但是这两者Spring创建好之后并没有关联,因为我们光读取是不够的,往哪读,这是这一章要阐述的!
读取核心代码
//bean定义的读取器
BeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(defaultBeanFactory);
BeanDefinitionReader按照源码注释里说的“是为了bean定义阅读的一个简单接口,使用Resource和String位置参数指定加载方法。”
我们再细看XmlBeanDefinitionReader
进入构造方法向上看父类里的方法:
protected AbstractBeanDefinitionReader(BeanDefinitionRegistry registry) {
Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
this.registry = registry;
// Determine ResourceLoader to use.
//这个bean的注册表对象是否是ResourceLoader的实例
if (this.registry instanceof ResourceLoader) {
//如果是那么就把这个注册bean的对象赋值给当前对象的ResourceLoader属性
this.resourceLoader = (ResourceLoader) this.registry;
}
else {
//否则给他一个默认的资源加载器
//this.resourceLoader = new DefaultResourceLoader();
this.resourceLoader = new PathMatchingResourcePatternResolver();
}
// Inherit Environment if possible
//和上面一样判断bean的注册对象是否是EnvironmentCapable的实例
if (this.registry instanceof EnvironmentCapable) {
//是的话,就获取环境对象并进行赋值
this.environment = ((EnvironmentCapable) this.registry).getEnvironment();
}
else {
//没有相应方法的话就给与一个标准环境
this.environment = new StandardEnvironment();
}
}
这里面有一个比较重要的对象Environment,进去看一下源码,就会发现他继承PropertyResolver,对profile的操作
进入他的继承类发现他主要是对Property属性进行操作
然后在看StandardEnvironment
对象:
我们可以看到他的上层也是实现了Environment接口,里面没有对应的构造函数!至此为止,AbstractBeanDefinitionReader构造完成!
读取器的加载
beanDefinitionReader.loadBeanDefinitions(resource);
进入源码:
/**
* Load bean definitions from the specified resource.
* @param resource the resource descriptor
* @return the number of bean definitions found
* @throws BeanDefinitionStoreException in case of loading or parsing errors
*/
//bean的解析数量
int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException;
它是一个接口,我们查看他的实现类XmlBeanDefinitionReader:
/**
* Load bean definitions from the specified XML file.
* @param resource the resource descriptor for the XML file
* @return the number of bean definitions found
* @throws BeanDefinitionStoreException in case of loading or parsing errors
*/
@Override
public int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException {
return loadBeanDefinitions(new EncodedResource(resource));
}
我们先看看EncodedResource对资源到底做了什么?这里我们直接进到核心代码块:
private EncodedResource(Resource resource, @Nullable String encoding, @Nullable Charset charset) {
super();
Assert.notNull(resource, "Resource must not be null");
this.resource = resource;
this.encoding = encoding;
this.charset = charset;
}
把传入的resource赋值给当前的Resource对象,返回回去!这是第一步!然后进入loadBeanDefinitions
方法:
public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {
Assert.notNull(encodedResource, "EncodedResource must not be null");
if (logger.isTraceEnabled()) {
logger.trace("Loading XML bean definitions from " + encodedResource);
}
//ThreadLocal<Set<EncodedResource>>,他返回一个初始值为4的hashset集合
Set<EncodedResource> currentResources = this.resourcesCurrentlyBeingLoaded.get();
//判断是否会产生循环依赖
if (!currentResources.add(encodedResource)) {
throw new BeanDefinitionStoreException(
"Detected cyclic loading of " + encodedResource + " - check your import definitions!");
}
//下面的代码下一章会重点说明
try (InputStream inputStream = encodedResource.getResource().getInputStream()) {
InputSource inputSource = new InputSource(inputStream);
if (encodedResource.getEncoding() != null) {
inputSource.setEncoding(encodedResource.getEncoding());
}
return doLoadBeanDefinitions(inputSource, encodedResource.getResource());
}
catch (IOException ex) {
throw new BeanDefinitionStoreException(
"IOException parsing XML document from " + encodedResource.getResource(), ex);
}
finally {
currentResources.remove(encodedResource);
if (currentResources.isEmpty()) {
this.resourcesCurrentlyBeingLoaded.remove();
}
}
}
这里面资源解析读取与加载完成之后,后面就是调用者如何使用的问题了!
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/16384.html