我是靠谱客的博主 时尚芒果,这篇文章主要介绍Spring源码解析之xml解析,现在分享给大家,希望可以做个参考。

文章目录

      • Xml解析
        • 默认标签的解析
        • 自定义标签解析
        • 注册BeanDefinition

Xml解析

首先进入AbstractApplicationContext的构造方法,追踪找到refresh()方法,这个方法是IOC容器初始化的核心方法。我们需要关注下obtainFreshBeanFactory()方法,主要是解析xml配置文件并封装成BeanDefinition对象

复制代码
1
2
3
4
5
6
public void refresh() throws BeansException, IllegalStateException { ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); // 进去 // ... }
复制代码
1
2
3
4
5
6
7
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() { refreshBeanFactory(); // 进去 ConfigurableListableBeanFactory beanFactory = getBeanFactory(); return beanFactory; }

创建BeanFactory对象,它是DefaultListableBeanFactory类型。

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
// org.springframework.context.support.AbstractRefreshableApplicationContext#refreshBeanFactory protected final void refreshBeanFactory() throws BeansException { try { DefaultListableBeanFactory beanFactory = createBeanFactory(); // 创建BeanFactory对象 beanFactory.setSerializationId(getId()); customizeBeanFactory(beanFactory); loadBeanDefinitions(beanFactory); // 进去 } }

接着把beanFactory委托(委托模式)给XmlBeanDefinitionReader对象去处理,这个reader对象主要用来加载所有的spring配置文件,接着reader把xml封装成document,交给(又是委托模式)BeanDefinitionDocumentReader对象去解析。spring配置文件中有两种类型的标签,一是默认标签,使用的默认命名空间,如<Bean/><import/><alias/>等,二是自定义标签,使用的自定义的命名空间,如<context:component-scan/>。解析xml的标签,会根据标签类型来决定走默认标签解析还是自定义标签解析。

复制代码
1
2
3
4
5
6
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException { XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory); // 委托模式 loadBeanDefinitions(beanDefinitionReader); // 进去,关注类似xxxBeanDefintions的方法 }

进入loadBeanDefinitions方法后,关注类似xxxBeanDefintions的方法,一直走下去,跳了n多层,果然大佬和我们不一样,如果是我,可能一个loadBeanDefinitions方法就搞定了。我们跳到了registerBeanDefinitions方法,这里又使用了委托模式,还是关注类似xxxBeanDefintions的方法

复制代码
1
2
3
4
5
6
7
8
public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException { BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader(); // 委托模式 int countBefore = getRegistry().getBeanDefinitionCount(); documentReader.registerBeanDefinitions(doc, createReaderContext(resource)); // 进入 return getRegistry().getBeanDefinitionCount() - countBefore; }

找到了parseBeanDefinitions方法,它会根据标签是默认标签还是自定义标签分别做不同处理。

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
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/>标签的解析

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) { if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) { importBeanDefinitionResource(ele); //import标签解析 } else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) { processAliasRegistration(ele); //alias标签解析 } else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) { processBeanDefinition(ele, delegate); // 重点看bean标签的解析 } else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) { // recurse doRegisterBeanDefinitions(ele); } }

解析bean标签的属性,如id、name、class、parent、scope、abstract等属性,然后封装到BeanDefinition对象中,解析完毕,再封装成BeanDefinitionHolder对象。

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) { // 解析并返回BeanDefinitionHolder BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele); if (bdHolder != null) { bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder); // 对BeanDefinitionHolder进行装饰,装饰者模式 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)); } }

解析并返回BeanDefinitionHolder

复制代码
1
2
3
4
5
6
7
8
public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, BeanDefinition containingBean) { String id = ele.getAttribute(ID_ATTRIBUTE); // id String nameAttr = ele.getAttribute(NAME_ATTRIBUTE); // name // ... // 进一步解析 AbstractBeanDefinition beanDefinition

最后

以上就是时尚芒果最近收集整理的关于Spring源码解析之xml解析的全部内容,更多相关Spring源码解析之xml解析内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(81)

评论列表共有 0 条评论

立即
投稿
返回
顶部