`
goodscript
  • 浏览: 72936 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

spring 3源码解析之如何解析"import", "alias", "bean"标签

阅读更多
解析的步骤:
1、加载web.xml、加载监听器
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
2、ContextLoaderListener
初始化initWebApplicationContext方法创建
org.springframework.web.context.support. XmlWebApplicationContext对象
3、XmlWebApplicationContext
调用loadBeanDefinitions方法,该方法主要做两件事情:初始化XmlBeanDefinitionReader、获取applicationContext.xml配置文件的路径、然后把事情交给XmlBeanDefinitionReader来处理
4、XmlBeanDefinitionReader
获取到applicationContext.xml配置文件的路径、读取配置文件的内容得到一个输入流、对输入流转码操作、然后封装成一个inputSource对象、再然后封装成一个document对象;在生成document对象的同事也生成了一个Resource对象、这两个对象分部是:document对象承载配置文件的主要内容信息、Resource承载配置文件的描述信息以及一些验证信息。
再由Resource对象创建一个XmlReaderContext。完成了以上操作XmlBeanDefinitionReader就把document对象和XmlReaderContext对象交给DefaultBeanDefinitionDocumentReader来处理
5、DefaultBeanDefinitionDocumentReader
1)、对XmlReaderContext装饰成一个BeanDefinitionParserDelegate对象;
2)、迭代document对象、把document对象拆分成Element元素逐个逐个解析;
3)、使用BeanDefinitionParserDelegate装饰对象解析Element元素或者说标签。
这里的Element元素有两种:一种是DefaultElement、另一种是CustomElement;DefaultElement包括alias、import、bean,CustomElement包括DefaultElement以外的所有元素
我们所关心的应该是第一中元素DefaultElement,看下DefaultBeanDefinitionDocumentReader解析该元素的方法:
private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
		if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {
			importBeanDefinitionResource(ele);
		}
		else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {
			processAliasRegistration(ele);
		}
		else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {
			processBeanDefinition(ele, delegate);
		}
	}



解析import标签的方法:
protected void importBeanDefinitionResource(Element ele) {
		String location = ele.getAttribute(RESOURCE_ATTRIBUTE);
		if (!StringUtils.hasText(location)) {
			getReaderContext().error("Resource location must not be empty", ele);
			return;
		}

		// Resolve system properties: e.g. "${user.dir}"
		location = SystemPropertyUtils.resolvePlaceholders(location);

		Set<Resource> actualResources = new LinkedHashSet<Resource>(4);

		// Discover whether the location is an absolute or relative URI 
		boolean absoluteLocation = false;
		try {
			absoluteLocation = ResourcePatternUtils.isUrl(location) || ResourceUtils.toURI(location).isAbsolute();
		}
		catch (URISyntaxException ex) {
			// cannot convert to an URI, considering the location relative
			// unless it is the well-known Spring prefix "classpath*:"
		}

		// Absolute or relative?
		if (absoluteLocation) {
			try {
				int importCount = getReaderContext().getReader().loadBeanDefinitions(location, actualResources);
				if (logger.isDebugEnabled()) {
					logger.debug("Imported " + importCount + " bean definitions from URL location [" + location + "]");
				}
			}
			catch (BeanDefinitionStoreException ex) {
				getReaderContext().error(
						"Failed to import bean definitions from URL location [" + location + "]", ele, ex);
			}
		}
		else {
			// No URL -> considering resource location as relative to the current file.
			try {
				int importCount;
				Resource relativeResource = getReaderContext().getResource().createRelative(location);
				if (relativeResource.exists()) {
					importCount = getReaderContext().getReader().loadBeanDefinitions(relativeResource);
					actualResources.add(relativeResource);
				}
				else {
					String baseLocation = getReaderContext().getResource().getURL().toString();
					importCount = getReaderContext().getReader().loadBeanDefinitions(
							StringUtils.applyRelativePath(baseLocation, location), actualResources);
				}
				if (logger.isDebugEnabled()) {
					logger.debug("Imported " + importCount + " bean definitions from relative location [" + location + "]");
				}
			}
			catch (IOException ex) {
				getReaderContext().error("Failed to resolve current resource location", ele, ex);
			}
			catch (BeanDefinitionStoreException ex) {
				getReaderContext().error("Failed to import bean definitions from relative location [" + location + "]",
						ele, ex);
			}
		}
		Resource[] actResArray = actualResources.toArray(new Resource[actualResources.size()]);
		getReaderContext().fireImportProcessed(location, actResArray, extractSource(ele));
	}

解析alias标签的方法:
	protected void processAliasRegistration(Element ele) {
		String name = ele.getAttribute(NAME_ATTRIBUTE);
		String alias = ele.getAttribute(ALIAS_ATTRIBUTE);
		boolean valid = true;
		if (!StringUtils.hasText(name)) {
			getReaderContext().error("Name must not be empty", ele);
			valid = false;
		}
		if (!StringUtils.hasText(alias)) {
			getReaderContext().error("Alias must not be empty", ele);
			valid = false;
		}
		if (valid) {
			try {
				getReaderContext().getRegistry().registerAlias(name, alias);
			}
			catch (Exception ex) {
				getReaderContext().error("Failed to register alias '" + alias +
						"' for bean with name '" + name + "'", ele, ex);
			}
			getReaderContext().fireAliasRegistered(name, alias, extractSource(ele));
		}
	}

解析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));
		}
	}


方法调用关系图:

  • 大小: 195.8 KB
分享到:
评论

相关推荐

    Spring源码解密之默认标签的解析

    总的来说,Spring通过源码解析XML配置文件中的默认标签,特别是`&lt;bean&gt;`标签,实现Bean定义的加载和注册,从而构建Bean的依赖关系图。理解这一过程对于深入掌握Spring的工作原理,优化配置,以及解决配置问题至关...

    Spring 源码分析(Bean的初始化)

    `BeanDefinitionParserDelegate`的作用是解析XML中的`&lt;bean&gt;`标签以及其他相关的元素,如`&lt;import&gt;`、`&lt;alias&gt;`等。在解析过程中,由于XML可以有嵌套的`&lt;beans&gt;`元素,`BeanDefinitionParserDelegate`使用一个parent...

    Spring源码总结.pdf

    - **常规标签解析**:包括`import`(导入其他配置)、`alias`(别名)、`bean`(定义Bean)等。在解析`bean`时,会创建`GenericBeanDefinition`对象,设置属性,处理元数据、lookup-method、replaced-method、构造...

    尚硅谷]_佟刚_Spring IOC 容器中 Bean 的生命周期.pdf

    3、import用于导入其他配置文件的Bean定义,这是为了加载多个配置文件,当然也可以把这些配置文件构造为一个数组(new String[] {“config1.xml”, config2.xml})传给ApplicationContext实现进行加载多个配置文件,...

    spring2.5.6源码

    rar包内含有spring2.5.6源码,解压即可使用 源代码分析,是一件既痛苦又快乐的事情,看别人写的代码是通过的,但当你能够看明白的时候,相信快乐也会随之而来,为了减少痛苦,更快的带来快乐,在这里希望通过这篇...

    spring源码1

    4. **BeanDefinition解析**:在解析过程中,会创建Bean的解析器,然后解析XML文档中的各个元素,如import、bean等。对于bean元素,会解析其name、id、alias,以及class属性等。如果允许覆盖,相同的bean定义会被覆盖...

    Spring2[1].5_IoC(控制反转)容器之容器与Bean(附示例)

    Spring IoC(Inversion of Control,控制反转)容器是Spring框架的核心组件之一,用于管理对象的生命周期以及依赖关系。通过Spring IoC容器,开发者能够更加轻松地管理和配置Java应用中的各种组件。 #### 二、...

    Spring容器 .ppt

    - **BeanFactory**:这是Spring中最基本的容器,它负责加载配置文件,解析Bean定义,然后根据这些定义实例化Bean。可以通过`XmlBeanFactory`类使用XML配置文件初始化一个BeanFactory。 - **ApplicationContext**:...

    spring-context-4.2.xsd.zip

    `spring-context-4.2.xsd`包含了一系列元素,如`beans`、`bean`、`import`、`alias`、`bean-definition`等,这些都是Spring配置中的关键组成部分。例如,`&lt;beans&gt;`元素是所有配置的根元素,`&lt;bean&gt;`元素用于定义一个...

    Spring入门.docx

    默认命名空间下,还有`beans`用于指定环境、`alias`用于配置别名、`import`用于导入其他配置文件。 Bean的实例化过程大致分为以下几个步骤:解析XML配置文件,将Bean定义转换成BeanDefinition对象,然后创建Bean...

    spring资料3

    在Spring中,bean的别名允许我们为同一个bean定义多个名字,可以通过`@Component("alias1", "alias2")`或者在XML配置中使用`id`和`name`属性来设定。这在某些场景下非常有用,比如接口的实现类切换。关于bean的作用...

    Spring中XML配置文件的十二个最佳方法.doc

    本文将详细解析Spring中XML配置文件的十二个最佳实践,主要关注前六个方法。 1. **避免使用自动绑定(Autowiring)** Spring的自动绑定功能允许框架通过类的自省自动注入依赖。虽然可以减少手动配置,但会导致配置...

    spring-beans-3.0.xsd

    此外,还有`&lt;alias&gt;`用于为bean创建别名,`&lt;import&gt;`引入其他配置文件,以及`&lt;property&gt;`用于设置bean的属性值等。 然而,随着Spring的发展,`spring-beans-3.1.xsd`在3.1版本中出现,引入了一些新特性以增强灵活性...

    Spring XML配置的12个技巧

    8. 使用`&lt;import&gt;`引入其他配置:当配置文件变得庞大时,可以将相关bean分组到单独的XML文件中,然后使用`&lt;import&gt;`标签导入这些文件,保持配置结构清晰。 9. 利用`&lt;alias&gt;`创建别名:为bean创建别名可以提供多个...

    Spring中xml的配置[定义].pdf

    除了这些核心概念,Spring的XML配置还包括其他元素,如`&lt;import&gt;`引入其他配置文件,`&lt;alias&gt;`为bean定义别名,以及`&lt;lookup-method&gt;`和`&lt;replaced-method&gt;`来处理方法的动态代理等。XML配置提供了一种声明式的方式...

    Spring2.0的配置2

    当有多个相同类型的bean时,`&lt;qualifier&gt;`标签可以帮助指定注入哪个特定的bean。 10. **使用`&lt;lookup-method&gt;`和`&lt;factory-method&gt;`**: 这两个元素允许在运行时动态创建bean,而不是在配置时静态定义。这对于...

    springmybatis

    mybatis实战教程mybatis in action之五与spring3集成附源码 mybatis实战教程mybatis in action之六与Spring MVC 的集成 mybatis实战教程mybatis in action之七实现mybatis分页源码下载 mybatis实战教程mybatis in ...

    SPRING 开发指南

    引入了如`&lt;import&gt;`、`&lt;alias&gt;`、`&lt;bean&gt;`标签的简写形式等,使得配置文件更易读、更易于维护。 5. **Annotation-driven Configuration**: 从Spring 2.5开始,Spring引入了注解驱动的配置,允许开发者在类或方法...

    Spring XML配置十二个最佳实践

    通过在主配置文件中使用`&lt;import&gt;`标签导入其他配置文件,可以有效地组织和管理不同的配置信息,使得每个文件专注于特定的功能模块。例如: ```xml &lt;import resource="billingServices.xml"/&gt; &lt;import resource=...

    spring+ibatis集成文档

    &lt;bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"&gt; &lt;/bean&gt; &lt;!-- 开启事务注解 --&gt; &lt;!-- 扫描Dao接口所在的包 --&gt; ``` 这里主要包括数据源...

Global site tag (gtag.js) - Google Analytics