Spring bean初始化(1) - XML解析

Spring bean的初始化源码分析-XML解析

XML解析部分,XML解析最终会将XML中配置的bean或者标签需要扫描的bean,都准备好,生成beanDefinition,用于后续的bean实例化

 

XmlBeanFactory bf = new XmlBeanFactory(new ClassPathResource("/spring-code-test.xml"));

 

 

DefaultListableBeanFactory 类是 spring bean 加载的核心类, XMLBeanFactory继承,实际是在里面封装了另一个类XmlBeanDefinitionReader, 这个类用于解析xml。本节主要讲这个类如何解析XML的。

public class XmlBeanFactory extends DefaultListableBeanFactory {

	private final XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(this);

	public XmlBeanFactory(Resource resource) throws BeansException {
		this(resource, null);
	}

	public XmlBeanFactory(Resource resource, BeanFactory parentBeanFactory) {
		super(parentBeanFactory);
		this.reader.loadBeanDefinitions(resource);
	}

}

 实际XML的加载过程封装在 XmlBeanDefinitionReader.loadBeanDefinitions 方法里了,实际过程是

1. 先对 输入的 文件进行 Resource 封装, new ClassPathResource("/spring-code-test.xml"), Resource对象传入XmlBeanDefinitionReader

2. XmlBeanDefinitionReader

   2.1 对输入对象进行encoding封装

   2.2 获取XML的验证模式,同时确认解析标签使用的XSD文档和对应标签解析的jar路径)

   2.3 加载XML文件,得到对应的Document对象

// XmlBeanDefinitionReader
public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {
		......
		try {
			InputStream inputStream = encodedResource.getResource().getInputStream();
			try {
				InputSource inputSource = new InputSource(inputStream);
				if (encodedResource.getEncoding() != null) {
					inputSource.setEncoding(encodedResource.getEncoding());
				}
				return doLoadBeanDefinitions(inputSource, encodedResource.getResource());
			}
......
}

protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource) {
		try {
                    // XML 生成 document对象,doLoadDocument 内部会确认 XSD文档和解析标签所使用的jar包
			Document doc = doLoadDocument(inputSource, resource);
			return registerBeanDefinitions(doc, resource);
		}
}

public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
            // 实际负责加载的document的类是 DefaultBeanDefinitionDocumentReader
		BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
		int countBefore = getRegistry().getBeanDefinitionCount();
		documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
		return getRegistry().getBeanDefinitionCount() - countBefore;
}

 

 

DefaultBeanDefinitionDocumentReader 类做的事情就是根据 document ,进行element解析

 
// DefaultBeanDefinitionDocumentReader 类
public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
		this.readerContext = readerContext;
		logger.debug("Loading bean definitions");
                // 获取root节点,进行解析
		Element root = doc.getDocumentElement();
		doRegisterBeanDefinitions(root);
	}

	/**
	 * Parse the elements at the root level in the document:
	 * "import", "alias", "bean".
	 * @param root the DOM root element of the document
	 */
    // 解析具体实现方法
	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)) {
                                                // 解析默认标签
						parseDefaultElement(ele, delegate);
					}
					else {
						delegate.parseCustomElement(ele);
					}
				}
			}
		}
		else {
			delegate.parseCustomElement(root);
		}
	}

        // 解析默认标签,bean标签相关
        protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
		BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
		if (bdHolder != null) {
			bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
			try {
				// Register the final decorated instance.
				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));
		}
	}
 
在上面的 processBeanDefinition 解析 bean标签时,实际会做四件事情 
(1)delegate.parseBeanDefinitionElement 方法会元素解析并返回 BeanDefinitionHolder,里面会包含class name id alias等信息
(2)若标签嵌套有自定义标签,则 decorateBeanDefinitionIfRequired 会处理;默认标签在第一步里已经循环调用解析完成了
(3)注册BeanDefinition, 将BeanDefinition放入 DefaultListableBeanFactory
(4)通知监听器(目前实现为空)
对于上面的(1),具体实现过程中,会生成 GenericBeanDefinition 类, 作为 BeanDefinition 的具体实现类,里面会初始化Class对象等bean的关键信息,贴一下BeanDefinition的继承结构, BeanDefinition <--- AbstractBeanDefinition <--- GenericBeanDefinition, RootBeanDefinition 其中 GenericBeanDefinition已经讲过, RootBeanDefinition会在bean的加载中使用。
对于xml的bean加载后的属性,基本都封装在 AbstractBeanDefinition 类中,可以去里面看到加载后的所有属性。
// BeanDefinitionReaderUtils 类
public static void registerBeanDefinition(
			BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry){

		// Register bean definition under primary name.
		String beanName = definitionHolder.getBeanName();
		registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());
......
}

// registry 的真正实现类 DefaultListableBeanFactory 类
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) {
......
    // ConcurrentHashMap<String, BeanDefinition> beanDefinitionMap 类型
    // 所以BeanDefinition都放在这里
    this.beanDefinitionMap.put(beanName, beanDefinition);
    this.beanDefinitionNames.add(beanName);
......
}
 
最后看到,xml的bean最终会封装成  BeanDefinition(真正实现是 GenericBeanDefinition ),存储到  DefaultListableBeanFactory的内部map中,用于后面bean加载使用
 
 
 
 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值