Bean定义解析注册流程总结

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


前言

对Spring IOC主流程中Bean定义解析注册流程分支的总结
这个分支的主要工作内容有两个
1 将xml中的配置信息解析成bean定义信息(BeannDefinition)对象
2 将BeanDefinition对象注册到工厂中,为后续实例化bean对象做准备

public abstract class AbstractXmlApplicationContext extends AbstractRefreshableConfigApplicationContext {
	protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
			// Create a new XmlBeanDefinitionReader for the given BeanFactory.
			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));
	
			// Allow a subclass to provide custom initialization of the reader,
			// then proceed with actually loading the bean definitions.
			initBeanDefinitionReader(beanDefinitionReader);
			loadBeanDefinitions(beanDefinitionReader);
		}
	
	protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {
			Resource[] configResources = getConfigResources();
			if (configResources != null) {
				reader.loadBeanDefinitions(configResources);
			}
			//容器初始化时设置了这个参数 他是xml配置文件的路径
			String[] configLocations = getConfigLocations();
			if (configLocations != null) {
				reader.loadBeanDefinitions(configLocations);
			}
		}
}

在继续跟方法之前,先介绍下DefinitionReader家族,防止后边跟晕了

一、DefinitionReader家族以及分工

在这里插入图片描述
DefinitionReader是家族的顶级接口,方法定义中可以看出主要就是用来加载bean定义信息的。其中loadBeanDefinitions有四个重载方法。画红框的三个重载方法统一由AbstractBeanDefinitionReader做了实现,唯一的一个框外的loadBeanDefinitions方法由其三个子类分别实现。

在这里插入图片描述
AbstractBeanDefinitionReader的主要目的就是将入参的字符串统一转化为Resource对象,便于子类处理。

1.1 继续跟踪代码reader.loadBeanDefinitions()

了解了BeafinitionReader家族的使命,接着跟踪加载方法。会跟踪到AbstractBeanDefinitionReader类中

public abstract class AbstractBeanDefinitionReader implements BeanDefinitionReader, EnvironmentCapable {
    //实现顶级接口中loadBeanDefinitions的方法之一
    @Override
	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;
	}

    //实现顶级接口中loadBeanDefinitions的方法之二
    @Override
	public int loadBeanDefinitions(String location) throws BeanDefinitionStoreException {
		return loadBeanDefinitions(location, null);
	}
	
	//这个方法完成了AbstractBeanDefinitionReader的主要使命,就是将入参统一成Resource对象
	public int loadBeanDefinitions(String location, @Nullable Set<Resource> actualResources) throws BeanDefinitionStoreException {
		//获取资源加载器 其实就是容器
		ResourceLoader resourceLoader = getResourceLoader();
		。。省略代码
		if (resourceLoader instanceof ResourcePatternResolver) {
			// Resource pattern matching available.
			try {
				//通过资源解析器获取资源
				Resource[] resources = ((ResourcePatternResolver) resourceLoader).getResources(location);
				//执行加载bean定义
				int count = loadBeanDefinitions(resources);
				。。省略代码
				return count;
			}
			catch (IOException ex) {
				。。省略代码
			}
		}
		else {
			// Can only load single resources by absolute URL.
			Resource resource = resourceLoader.getResource(location);
			//执行加载bean定义
			int count = loadBeanDefinitions(resource);
			。。省略代码
			return count;
		}
	}
	 //实现顶级接口中loadBeanDefinitions的方法之三
	@Override
	public int loadBeanDefinitions(Resource... resources) throws BeanDefinitionStoreException {
		Assert.notNull(resources, "Resource array must not be null");
		int count = 0;
		for (Resource resource : resources) {
		    //最后交给子类来实现
			count += loadBeanDefinitions(resource);
		}
		return count;
	}
}

1.2 继续跟踪代码reader.loadBeanDefinitions()

继续跟踪会跟踪到具体的子类XmlBeanDefinitionReader中

public class XmlBeanDefinitionReader extends AbstractBeanDefinitionReader {
    //实现顶级接口中loadBeanDefinitions的方法之四
	@Override
	public int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException {
		return loadBeanDefinitions(new EncodedResource(resource));
	}
	
	//加载处理
	public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {
			。。。省略代码
			try (InputStream inputStream = encodedResource.getResource().getInputStream()) {
				InputSource inputSource = new InputSource(inputStream);
				。。。省略代码
				//真正的执行加载
				return doLoadBeanDefinitions(inputSource, encodedResource.getResource());
			}
			catch (IOException ex) {
				。。。省略代码
			}
			finally {
		     	。。。省略代码
			}
		}
    //真正加载处理
    protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
			throws BeanDefinitionStoreException {
		try {
		    //将资源加载成Document对象 到这里加载结束了 剩下的是注册环节
			Document doc = doLoadDocument(inputSource, resource);
			//执行注册
			int count = registerBeanDefinitions(doc, resource);
			。。。省略代码
			return count;
		}
			。。。省略代码
	}
	//注册bean定义信息
    public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
		BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
		int countBefore = getRegistry().getBeanDefinitionCount();
		//委托给BeanDefinitionDocumentReader类完成后续的注册流程
		documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
		return getRegistry().getBeanDefinitionCount() - countBefore;
	}

}

二、BeanDefinitionDocumentReader

继续跟踪documentReader.registerBeanDefinitions方法,会从BeanDefinitionReader家族来到BeanDefinitionDocumentReader家族。虽然名字很像但是他们没有血缘关系
在这里插入图片描述
这个家族的使命就是注册bean,并且只有DefaultBeanDefinitionDocumentReader一个实现类

public class DefaultBeanDefinitionDocumentReader implements BeanDefinitionDocumentReader {
    //注册bean定义
	@Override
	public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
		this.readerContext = readerContext;
		//真正执行bean定义注册
		doRegisterBeanDefinitions(doc.getDocumentElement());
	}

    protected void doRegisterBeanDefinitions(Element root) {
		。。。省略注释
		BeanDefinitionParserDelegate parent = this.delegate;
		//委托给BeanDefinitionParserDelegate来执行解析
		this.delegate = createDelegate(getReaderContext(), root, parent);
		。。。省略代码
		preProcessXml(root);
		//解析bean定义信息 在这里
		parseBeanDefinitions(root, this.delegate);
		postProcessXml(root);
		this.delegate = parent;
	}
	//解析的目的是将Element元素解析成BeanDefinition对象最终注入到工厂中
    protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
		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)) {
					    //解析默认标签(bean标签在这里 所以继续跟这个方法)
						parseDefaultElement(ele, delegate);
					}
					else {
					    //解析自定义标签(aop mvc 都是自定义标签) 后续总结aop时在跟这里
						delegate.parseCustomElement(ele);
					}
				}
			}
		}
		else {
		    //解析自定义标签(aop mvc 都是自定义标签) 后续总结aop时在跟这里
			delegate.parseCustomElement(root);
		}
	}
    //解析默认标签
    protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
        //这里完成了解析 BeanDefinitionHolder内部封装了bean定义信息
		BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
		if (bdHolder != null) {
			bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
			try {
				//将bean定义信息注册到工作
				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));
		}
	}
}

三、BeanDefinitionParserDelegate

这个类是解析注册流程中最后的一个委托了,最后在大致跟以下delegate.parseBeanDefinitionElement(ele)方法

public class BeanDefinitionParserDelegate {
	@Nullable
	public BeanDefinitionHolder parseBeanDefinitionElement(Element ele) {
	    //继续跟这里
		return parseBeanDefinitionElement(ele, null);
	}
	
	public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, @Nullable BeanDefinition containingBean) {
	    //解析出标签中的id
		String id = ele.getAttribute(ID_ATTRIBUTE);
		//解析出标签中的name
		String nameAttr = ele.getAttribute(NAME_ATTRIBUTE);

		List<String> aliases = new ArrayList<>();
		if (StringUtils.hasLength(nameAttr)) {
			String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, MULTI_VALUE_ATTRIBUTE_DELIMITERS);
			aliases.addAll(Arrays.asList(nameArr));
		}
		//默认bean名称是id
		String beanName = id;
		//如果没定义id 但是有name 那么就用name
		if (!StringUtils.hasText(beanName) && !aliases.isEmpty()) {
			beanName = aliases.remove(0);
			if (logger.isTraceEnabled()) {
				logger.trace("No XML 'id' specified - using '" + beanName +
						"' as bean name and " + aliases + " as aliases");
			}
		}
		。。。省略代码
		//获取bean定义
		AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean);
		if (beanDefinition != null) {
			。。。省略代码
			String[] aliasesArray = StringUtils.toStringArray(aliases);
			//将bean定义信息封装到BeanDefinitionHolder对象中
			return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray);
		}
		return null;
	}
	
	@Nullable
	public AbstractBeanDefinition parseBeanDefinitionElement(
			Element ele, String beanName, @Nullable BeanDefinition containingBean) {

		this.parseState.push(new BeanEntry(beanName));
		//获取类全路径名称
		String className = null;
		if (ele.hasAttribute(CLASS_ATTRIBUTE)) {
			className = ele.getAttribute(CLASS_ATTRIBUTE).trim();
		}
		//看看有没有父标签
		String parent = null;
		if (ele.hasAttribute(PARENT_ATTRIBUTE)) {
			parent = ele.getAttribute(PARENT_ATTRIBUTE);
		}

		try {
		    //这里创建了一个bean定义对象
			AbstractBeanDefinition bd = createBeanDefinition(className, parent);
			//解析流程继续跟这里
			parseBeanDefinitionAttributes(ele, beanName, containingBean, bd);
			bd.setDescription(DomUtils.getChildElementValueByTagName(ele, DESCRIPTION_ELEMENT));
           ...省略代码
			return bd;
		}
		...省略代码
	}
	//最终的解析流程
    public AbstractBeanDefinition parseBeanDefinitionAttributes(Element ele, String beanName,
			@Nullable BeanDefinition containingBean, AbstractBeanDefinition bd) {
		//解析作用域 scope
		if (ele.hasAttribute(SINGLETON_ATTRIBUTE)) {
			error("Old 1.x 'singleton' attribute in use - upgrade to 'scope' declaration", ele);
		}
		else if (ele.hasAttribute(SCOPE_ATTRIBUTE)) {
			bd.setScope(ele.getAttribute(SCOPE_ATTRIBUTE));
		}
		else if (containingBean != null) {
			// Take default from containing bean in case of an inner bean definition.
			bd.setScope(containingBean.getScope());
		}
		//解析是否是抽象的
		if (ele.hasAttribute(ABSTRACT_ATTRIBUTE)) {
			bd.setAbstract(TRUE_VALUE.equals(ele.getAttribute(ABSTRACT_ATTRIBUTE)));
		}
		//解析是否懒加载
		String lazyInit = ele.getAttribute(LAZY_INIT_ATTRIBUTE);
		if (isDefaultValue(lazyInit)) {
			lazyInit = this.defaults.getLazyInit();
		}
		bd.setLazyInit(TRUE_VALUE.equals(lazyInit));
		...后边还有很多 可以自己看源码
		return bd;
	}

}

总结

1 容器将解析和加载bean定义信息的任务委托给了BeanDefinitionReader来处理
2 BeanDefinitionReader的子类AbstractBeanDefinitionReader将加载的入参从字符串统一封装成了Resource对象交给子类继续处理
3 其中的一个子类XMLBeanDefinitionReader将Resource封装成了Document对象并委托BeanDefinitionDocumentReader完成后续的解析和注册
4 BeanDefinitionDocumentReader的唯一实现类DefaultBeanDefinitionDocumentReader委托BeanDefinitionParserDelegate将Document对象解析成BeanDefinition对象最终将其注册到BeanFactory工厂中

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值