Spring IOC初始化源码分析之(二)obtainFreshBeanFactory----获取bean工厂

源码分析

	protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
	  	//刷新bean工厂
		refreshBeanFactory();
		//返回工厂
		return getBeanFactory();
	}

代码显示,获取bean工厂的过程分两步:第一步刷新,第二步返回;(如同将大象关进冰箱

那么,刷新工厂需要做哪些事呢,下面看代码:

	protected final void refreshBeanFactory() throws BeansException {
		//若bean工厂已存在,则销毁bean工厂,重新创建
		if (hasBeanFactory()) {
			destroyBeans();
			closeBeanFactory();
		}
		try {
			//创建bean工厂对象
			DefaultListableBeanFactory beanFactory = createBeanFactory();
			//为了序列话指定id,如果需要的话,让这个BeanFactory从id反序列化到BeanFactory对象
			beanFactory.setSerializationId(getId());
			//自定义bean工厂
			customizeBeanFactory(beanFactory);
			//加载bean定义对象
			loadBeanDefinitions(beanFactory);
			this.beanFactory = beanFactory;
		}
		catch (IOException ex) {
			throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
		}
	}

观察代码,能够清晰的看到刷新的过程,
(1)首先判断是否已经存在,若存在,则销毁;
(2)再创建一个DefaultListableBeanFactory 对象;
(3)设置序列化id,此id与序列化相关,能够根据id反序列化为一个对象;
(4)定制此上下文使用的内部bean工厂;
(5)加载bean定义对象;

customizeBeanFactory(beanFactory)代码如下:

	protected void customizeBeanFactory(DefaultListableBeanFactory beanFactory) {
		//设置是否允许bean定义重写
		if (this.allowBeanDefinitionOverriding != null) {
			beanFactory.setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
		}
		//设置是否允许bean循环引用
		if (this.allowCircularReferences != null) {
			beanFactory.setAllowCircularReferences(this.allowCircularReferences);
		}
	}

这段代码的功能是什么呢?此处与spring的拓展有关,暂且不做详细讨论,且记作为拓展点1,日后再行探讨;

看下一段重点loadBeanDefinitions(beanFactory),代码如下:

	@Override
	protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
		// Create a new XmlBeanDefinitionReader for the given BeanFactory.
		//根据给定bean工厂对象创建建一个bean定义信息读取器
		XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
		//对环境变量进行设置
		// Configure the bean definition reader with this context's
		// resource loading environment.
		//设置资源加载器
		beanDefinitionReader.setEnvironment(this.getEnvironment());
		beanDefinitionReader.setResourceLoader(this);
		beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));
		//初始化reader
		// Allow a subclass to provide custom initialization of the reader,
		// then proceed with actually loading the bean definitions.
		initBeanDefinitionReader(beanDefinitionReader);
		//加载bean信息
		loadBeanDefinitions(beanDefinitionReader);
	}

阅读代码,执行顺序如下:
(1)为给定的bean工厂创建新的XmlBeanDefinitionReader对象。
(2)经过一系列的设置,加载bean信息。

loadBeanDefinitions(beanDefinitionReader)代码如下

	protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {
		//循环加载资源配置文件
		Resource[] configResources = getConfigResources();
		if (configResources != null) {
			reader.loadBeanDefinitions(configResources);
		}
		String[] configLocations = getConfigLocations();
		if (configLocations != null) {
			reader.loadBeanDefinitions(configLocations);
		}
	}

观察代码,调用AbstrcatBeanDefinitionReaderloadBeanDefinitions(configResources)方法,循环加载资源配置文件(.xml)。
loadBeanDefinitions(configResources)代码如下:

	public int loadBeanDefinitions(String... locations) throws BeanDefinitionStoreException {
		Assert.notNull(locations, "Location array must not be null");
		int count = 0;
		for (String location : locations) {
			count += loadBeanDefinitions(location);
		}
		return count;
	}

一路跟踪,经过一系列骚操作,最终成功将String形式资源路径转换为Resource类型,并进入以下方法

	protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
			throws BeanDefinitionStoreException {

		try {
			//转换为document对象,方便对各个元素进行解析
			Document doc = doLoadDocument(inputSource, resource);
			//解析document对象
			int count = registerBeanDefinitions(doc, resource);
			if (logger.isDebugEnabled()) {
				logger.debug("Loaded " + count + " bean definitions from " + resource);
			}
			return count;
		}
	    catch(Exception ex){
	    ...
	    }
	}

在此方法中,将resouce转换为document对象,方便对其进行解析,进入解析document对象过程registerBeanDefinitions代码

	public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
		//创建document解析器
		BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
		//获取已经注册进ioc容器的bean的数量
		int countBefore = getRegistry().getBeanDefinitionCount();
		//注册bean定义信息
		documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
		return getRegistry().getBeanDefinitionCount() - countBefore;
	}

显然,代码核心为registerBeanDefinitions,注册beanDefinition,代码如下:

	public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
		this.readerContext = readerContext;
		doRegisterBeanDefinitions(doc.getDocumentElement());
	}


	protected void doRegisterBeanDefinitions(Element root) {
		BeanDefinitionParserDelegate parent = this.delegate;
		this.delegate = createDelegate(getReaderContext(), root, parent);
		if (this.delegate.isDefaultNamespace(root)) {
			String profileSpec = root.getAttribute(PROFILE_ATTRIBUTE);
			if (StringUtils.hasText(profileSpec)) {
				String[] specifiedProfiles = StringUtils.tokenizeToStringArray(
						profileSpec, BeanDefinitionParserDelegate.MULTI_VALUE_ATTRIBUTE_DELIMITERS);
				if (!getReaderContext().getEnvironment().acceptsProfiles(specifiedProfiles)) {
					if (logger.isDebugEnabled()) {
						logger.debug("Skipped XML bean definition file due to specified profiles [" + profileSpec +
								"] not matching: " + getReaderContext().getResource());
					}
					return;
				}
			}
		}
		//加载前的定制化操作,由子类实现
		preProcessXml(root);
		//从root元素开始解析
		parseBeanDefinitions(root, this.delegate);
		//加载后的定制化操作,由子类实现
		postProcessXml(root);

		this.delegate = parent;
	}

略过无关操作,找到其关键:parseBeanDefinitions(root, this.delegate);,代码如下:

protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
		//是否是spring的默认空间
		if (delegate.isDefaultNamespace(root)) {
			NodeList nl = root.getChildNodes();
			for (int i = 0; i < nl.getLength(); i++) {
				Node node = nl.item(i);
				//判断当前节点是否有效节点
				if (node instanceof Element) {
					Element ele = (Element) node;
					if (delegate.isDefaultNamespace(ele)) {
						//是Spring自定义的则使用默认的方法解析
						parseDefaultElement(ele, delegate);
					}
					else {
						//使用代理的方法解析
						delegate.parseCustomElement(ele);
					}
				}
			}
		}
		else {
			delegate.parseCustomElement(root);
		}
	}

以下是ele包含的我们在xml中定义的信息
在这里插入图片描述
在默认的解析方法parseDefaultElement中,代码如下

private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
		//import节点
		if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {
			importBeanDefinitionResource(ele);
		}
		//alias节点
		else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {
			processAliasRegistration(ele);
		}
		//bean节点
		else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {
			processBeanDefinition(ele, delegate);
		}
		//nested节点
		else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {
			// recurse
			doRegisterBeanDefinitions(ele);
		}
	}

当前我们为bean,进入bean节点,执行processBeanDefinition方法:

protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
		//根据节点信息,生成beanDefinitionHolder对象,里面包含了BeanDefinition
		BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
		if (bdHolder != null) {
			bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
			try {
				// Register the final decorated instance.
				//注册BeanDefinition
				BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
			}
			catch (BeanDefinitionStoreException ex) {
				getReaderContext().error("Failed to register bean definition with name '" +
						bdHolder.getBeanName() + "'", ele, ex);
			}
			// Send registration event.
			getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
		}
	}

方法中,首先根据节点信息,生成BeanDefinitionHolder对象,以下是beanDefinitionHolder下的信息:
在这里插入图片描述
我们能看到,在bdHolder中,包含了beanDefinition信息,里面包含了bean的类信息以及id,生成beanDefinition后,我们将其注册进bean工厂,查看registerBeanDefinition方法:

public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
			throws BeanDefinitionStoreException {

		Assert.hasText(beanName, "Bean name must not be empty");
		Assert.notNull(beanDefinition, "BeanDefinition must not be null");

		if (beanDefinition instanceof AbstractBeanDefinition) {
			try {
				((AbstractBeanDefinition) beanDefinition).validate();
			}
			catch (BeanDefinitionValidationException ex) {
				throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
						"Validation of bean definition failed", ex);
			}
		}

		BeanDefinition existingDefinition = this.beanDefinitionMap.get(beanName);
		if (existingDefinition != null) {
			//无关代码
			...
			this.beanDefinitionMap.put(beanName, beanDefinition);
		}
		else {
			if (hasBeanCreationStarted()) {
				// Cannot modify startup-time collection elements anymore (for stable iteration)
				synchronized (this.beanDefinitionMap) {
					this.beanDefinitionMap.put(beanName, beanDefinition);
					List<String> updatedDefinitions = new ArrayList<>(this.beanDefinitionNames.size() + 1);
					updatedDefinitions.addAll(this.beanDefinitionNames);
					updatedDefinitions.add(beanName);
					this.beanDefinitionNames = updatedDefinitions;
					removeManualSingletonName(beanName);
				}
			}
			else {
				// Still in startup registration phase
				this.beanDefinitionMap.put(beanName, beanDefinition);
				this.beanDefinitionNames.add(beanName);
				removeManualSingletonName(beanName);
			}
			this.frozenBeanDefinitionNames = null;
		}

		if (existingDefinition != null || containsSingleton(beanName)) {
			resetBeanDefinition(beanName);
		}
		else if (isConfigurationFrozen()) {
			clearByTypeCache();
		}
	}

忽略无关代码,看到关键,核心便是this.beanDefinitionMap.put(beanName, beanDefinition);,以bean的id或name为键,BeanDefinition为值,放入BeanFactory的beanDefinitionMap中,以下是当前bean工厂的属性值
在这里插入图片描述
至此,bean工厂初步完成,此时已将读取的bean定义信息生成BeanDefinition,并存入bean工厂;

小结

在获取bean工厂的过程可总结如下:

  1. 创建BeanFactory对象;
  2. 根据工厂对象创建BeanDefinitionReader对象;
  3. 将xml文件加载入读取器;
  4. 将文件解析,将每个bean节点都生成BeanDefinition,并封装为一个BeanDefinitionHoler;
  5. 将生成的BeanDefinition存入工厂对象的BeanDefinitionMap中;
  6. 返回bean工厂对象;
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值