文章目录
-
-
- Xml解析
-
- 默认标签的解析
- 自定义标签解析
- 注册BeanDefinition
-
Xml解析
首先进入AbstractApplicationContext
的构造方法,追踪找到refresh()
方法,这个方法是IOC容器初始化的核心方法。我们需要关注下obtainFreshBeanFactory()
方法,主要是解析xml配置文件并封装成BeanDefinition对象
1
2
3
4
5
6public void refresh() throws BeansException, IllegalStateException { ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); // 进去 // ... }
1
2
3
4
5
6
7protected 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
6protected 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
8public 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
28protected 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
21private 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
22protected 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
8public 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解析内容请搜索靠谱客的其他文章。
发表评论 取消回复