概述
文章目录
-
-
- Xml解析
-
- 默认标签的解析
- 自定义标签解析
- 注册BeanDefinition
-
Xml解析
首先进入AbstractApplicationContext
的构造方法,追踪找到refresh()
方法,这个方法是IOC容器初始化的核心方法。我们需要关注下obtainFreshBeanFactory()
方法,主要是解析xml配置文件并封装成BeanDefinition对象
public void refresh() throws BeansException, IllegalStateException {
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); // 进去
// ...
}
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
refreshBeanFactory(); // 进去
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
return beanFactory;
}
创建BeanFactory
对象,它是DefaultListableBeanFactory
类型。
// 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的标签,会根据标签类型来决定走默认标签解析还是自定义标签解析。
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory); // 委托模式
loadBeanDefinitions(beanDefinitionReader); // 进去,关注类似xxxBeanDefintions的方法
}
进入loadBeanDefinitions方法后,关注类似xxxBeanDefintions的方法,一直走下去,跳了n多层,果然大佬和我们不一样,如果是我,可能一个loadBeanDefinitions方法就搞定了。我们跳到了registerBeanDefinitions方法,这里又使用了委托模式,还是关注类似xxxBeanDefintions的方法
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方法,它会根据标签是默认标签还是自定义标签分别做不同处理。
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/>
标签的解析
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
对象。
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
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解析所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复