Spring源码解析之配置读取器加载流程解析

前文

在之前介绍了资源与工厂创建流程解析,但是这两者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();
			}
		}
	}

这里面资源解析读取与加载完成之后,后面就是调用者如何使用的问题了!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值