`
diecui1202
  • 浏览: 97947 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

Spring 3-Bean的解析

阅读更多

一、Bean的解析(以XmlBeanFactory为例来说明)

1、构造级联容器

AbstractBeanFactory.java

public void setParentBeanFactory(BeanFactory parentBeanFactory) {
        // 如果当前容器已经指定了父容器,且新的父容器与当前的父容器不相同,则出错了;
	if (this.parentBeanFactory != null && this.parentBeanFactory != parentBeanFactory) {
		throw new IllegalStateException("Already associated with parent BeanFactory: " + this.parentBeanFactory);
	}
	this.parentBeanFactory = parentBeanFactory;
}
 
2、生成XmlBeanDefinitionReader

XmlBeanFactory.java

// new一个XmlBeanDefinitionReader,在解析bean配置文件时,直接将bean定义信息放到BeanDefinitionRegistry里
// 这里把当前容器作为参数传入,是因为XmlBeanFactory实现了BeanDefinitionRegistry接口
private final XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(this);
 
3、利用上面构造的reader解析XML文件,装载bean
this.reader.loadBeanDefinitions(resource);

解析
XmlBeanDefinitionReader.java

public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {
	Assert.notNull(encodedResource, "EncodedResource must not be null");
	if (logger.isInfoEnabled()) {
		logger.info("Loading XML bean definitions from " + encodedResource.getResource());
	}

	Set currentResources = (Set) this.resourcesCurrentlyBeingLoaded.get();
	if (currentResources == null) {
		currentResources = new HashSet(4);
		this.resourcesCurrentlyBeingLoaded.set(currentResources);
	}
        // 这里使用ThreadLocal防止循环装载bean
	if (!currentResources.add(encodedResource)) {
		throw new BeanDefinitionStoreException(
				"Detected recursive loading of " + encodedResource + " - check your import definitions!");
	}
	try {
		InputStream inputStream = encodedResource.getResource().getInputStream();
		try {
			InputSource inputSource = new InputSource(inputStream);
			if (encodedResource.getEncoding() != null) {
				inputSource.setEncoding(encodedResource.getEncoding());
			}
                        // 从这里开始解析并装载bean
			return doLoadBeanDefinitions(inputSource, encodedResource.getResource());
		}
		finally {
			inputStream.close();
		}
	}
	catch (IOException ex) {
		throw new BeanDefinitionStoreException(
				"IOException parsing XML document from " + encodedResource.getResource(), ex);
	}
	finally {
                // 装载完后,移除该bean定义文件
		currentResources.remove(encodedResource);
		if (currentResources.isEmpty()) {
			this.resourcesCurrentlyBeingLoaded.set(null);
		}
	}
}

 XmlBeanDefinitionReader.java

protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
		throws BeanDefinitionStoreException {
	try {
		int validationMode = getValidationModeForResource(resource);
		Document doc = this.documentLoader.loadDocument(
				inputSource, getEntityResolver(), this.errorHandler, validationMode, isNamespaceAware());
                // 对XML进行校验后,注册bean信息
		return registerBeanDefinitions(doc, resource);
	}
        ...
}

 XmlBeanDefinitionReader.java

public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
	...

	BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
	int countBefore = getRegistry().getBeanDefinitionCount();
        // 交由DefaultBeanDefinitionDocumentReader完成读取bean的工作
	documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
        // 返回当前resource注册到容器中的bean的数量
	return getRegistry().getBeanDefinitionCount() - countBefore;
}

 DefaultBeanDefinitionDocumentReader.java

public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
	this.readerContext = readerContext;

	logger.debug("Loading bean definitions");
	Element root = doc.getDocumentElement();

	BeanDefinitionParserDelegate delegate = createHelper(readerContext, root);

	preProcessXml(root);
        // 由代理类BeanDefinitionParserDelegate完成解析
	parseBeanDefinitions(root, delegate);
	postProcessXml(root);
}

 DefaultBeanDefinitionDocumentReader.java

protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
	if (delegate.isDefaultNamespace(root.getNamespaceURI())) {
		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;
				String namespaceUri = ele.getNamespaceURI();
				if (delegate.isDefaultNamespace(namespaceUri)) {
                                        // 解析每个element
					parseDefaultElement(ele, delegate);
				}
				else {
					delegate.parseCustomElement(ele);
				}
			}
		}
	}
	else {
		delegate.parseCustomElement(root);
	}
}

 DefaultBeanDefinitionDocumentReader.java

private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
        // 如果元素名是import
	if (DomUtils.nodeNameEquals(ele, IMPORT_ELEMENT)) {
		importBeanDefinitionResource(ele);
	}
        // 如果元素名是alias
	else if (DomUtils.nodeNameEquals(ele, ALIAS_ELEMENT)) {
		processAliasRegistration(ele);
	}
        // 如果元素名是bean
	else if (DomUtils.nodeNameEquals(ele, BEAN_ELEMENT)) {
		processBeanDefinition(ele, delegate);
	}
}
 

从这里可以看到:

  1. 如果bean配置文件中使用到了import元素,也是在这里处理的,其处理过程和上面的一致;
  2. 如果是别名,则直接将别名注册到beanName上;

生成BeanDefinition
DefaultBeanDefinitionDocumentReader.java

protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
        // 解析element的亚属性,封装成BeanDefinition,然后和beanName、别名(主属性)一起组装成BeanDefinitionHolder
        // 这里把解析bean元素的工作完成委托给BeanDefinitionParseDelegate类来完成
	BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
	if (bdHolder != null) {
		bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
		try {
                        // 注册刚才生成的BeanDefinitionHolder到容器中
			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));
	}
}

注册到容器中
BeanDefinitionReaderUtils.java

public static void registerBeanDefinition(
		BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
		throws BeanDefinitionStoreException {

	// 注册bean信息
	String beanName = definitionHolder.getBeanName();
	registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());

	// 注册别名
	String[] aliases = definitionHolder.getAliases();
	if (aliases != null) {
		for (int i = 0; i < aliases.length; i++) {
			registry.registerAlias(beanName, aliases[i]);
		}
	}
}
 
4、小结
  1. 其实,这里看着这么多代码,但其作用只有一个,那就是解析XML里的每个元素,获取Spring规范定义的bean的属性值,然后生成BeanDefinition实例;
  2. 上面提到一点,解析bean的繁锁工作全部由BeanDefinitionParseDelegate类来完成,从这一点也可以看出,Spring中类的职责分工相当的明确;
分享到:
评论

相关推荐

    spring-framework-master

    《Spring框架深度解析》 Spring Framework,作为Java开发领域中的基石,是企业级应用开发的首选框架。"spring-framework-master"这一压缩包包含了Spring框架的完整源码,为我们提供了深入理解这一强大工具的绝佳...

    spring-aop-3.0.xsd spring-beans-3.0 spring-context-3.0.xsd spring-mvc-3.1.xsd

    3. **spring-context-3.0.xsd**: Spring Context 是 Spring 框架的扩展,它提供了更丰富的上下文环境,包括国际化、事件广播、AOP 代理等功能。`spring-context-3.0.xsd` 文件包含了在上下文环境中配置的各种元素...

    Spring--2.Spring 中的 Bean 配置-3

    Spring提供了基于类型、名称等多种方式进行依赖解析。 综上所述,Spring中的Bean配置提供了丰富的选项来满足不同场景的需求,无论是简单的单例对象,还是复杂的依赖关系,都可以通过灵活的配置方式进行管理。通过...

    撸一撸Spring Framework-IoC-BeanDefinition(csdn)————程序.pdf

    它解析`&lt;bean&gt;`标签,从中提取出`class`属性(定义bean的实现类)、`parent`属性(定义父bean)、以及其他的属性,如`scope`(作用域)、`abstract`(是否为抽象bean)、`lazy-init`(是否延迟初始化)、`autowire`...

    Spring实战2-Bean注入详解的源代码

    xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" xmlns:context=...

    spring-context-3.2.0 spring-core-3.2.0 等齐全的Spring jar包

    这里提到的是一组完整的Spring库,包括`spring-core`、`spring-context`、`spring-webmvc`、`spring-web`、`spring-beans`、`spring-test`、`spring-jdbc`、`spring-orm`、`spring-aop`和`spring-tx`,它们都是3.2.0...

    springframework-4.2.5

    3. **Spring Context**:`spring-context-4.2.5.RELEASE.jar`扩展了Spring Core的功能,提供了一个应用上下文,它是bean的容器,可以管理和查找bean,并且支持消息处理、AOP(Aspect Oriented Programming,面向切面...

    跟我学spring3-源码.

    《跟我学Spring3-源码》教程是一份深入解析Spring框架3.x版本核心源码的教育资源,适合对Java和J2EE技术有一定基础的开发者学习。本教程旨在帮助读者理解Spring框架的工作原理,提高在实际项目中的应用能力。通过...

    spring-framework-reference-4.3.19.pdf

    ### Spring Framework 4.3.19版本关键知识点解析 #### 一、Spring框架概览 **1. 开始使用Spring** - **Spring框架简介**:Spring是一个开源框架,最初由Rod Johnson创建,旨在简化企业级Java应用的开发。Spring...

    官方原版源码spring-framework-5.1.4.RELEASE.zip

    《Spring Framework 5.1.4源码深度解析》 Spring Framework是Java开发中的核心框架,它为构建高质量的企业级应用提供了全面的支持。5.1.4版本是Spring的重要里程碑,引入了诸多新特性和改进,旨在提升性能、增强可...

    spring-framework-1.0-m2.zip

    《Spring Framework 1.0-m2深度解析》 Spring Framework,作为Java开发中不可或缺的开源框架,自其诞生以来就以其强大的IoC(Inversion of Control)和AOP(Aspect Oriented Programming)特性赢得了广大开发者的心...

    官方完整包 spring-framework-5.3.7.RELEASE-dist.zip

    - **Bean容器**:是Spring的核心,负责管理对象的生命周期和依赖关系,通过XML或注解实现bean的配置。 - **AOP**:提供面向切面编程,允许开发者定义方法拦截器和切点,实现代码的解耦和模块化。 3. **模块详解**...

    spring-framework-4.3.30.RELEASE-docs.zip

    3. **Bean容器** Spring Bean容器(ApplicationContext)负责创建、配置和管理应用中的对象。它可以读取XML、Java注解或其他配置源来创建和管理Bean。 4. **IoC配置** 在4.3.30.RELEASE中,Spring支持XML、Java...

    spring3-dtd

    1. **Bean定义**:在Spring 3的DTD配置中,我们可以定义bean的实例,指定其类、构造函数参数、属性注入、初始化方法和销毁方法。例如,`&lt;bean id="exampleBean" class="com.example.ExampleClass"&gt;`。 2. **依赖...

    spring-framework-4.3.0.RELEASE(源码已经成功编译)

    《Spring Framework 4.3.0.RELEASE源码解析与深度探索》 Spring Framework作为Java领域最广泛应用的轻量级框架之一,其4.3.0.RELEASE版本的发布为开发者提供了更稳定、高效的服务。这个版本的成功编译,意味着我们...

    intellij-spring-assistant-1.0.4.zip

    2. 快速导航:通过快捷键或菜单,可以快速跳转到Spring Bean定义的位置,便于查看和修改配置。 3. 智能提示:在编写XML配置文件时,插件会提供自动提示,减少错误和遗漏。 4. 依赖注入分析:分析项目中的Bean依赖...

    官方原版源码spring-framework-5.2.3.RELEASE.zip

    《Spring Framework 5.2.3源码深度解析》 Spring Framework是Java开发中的核心框架,它为构建高质量的应用提供了全面的基础设施。5.2.3版本是Spring的一个稳定版本,包含了众多改进和新特性。这个官方原版源码包为...

    spring3--最小系统

    9. **依赖注入**:Spring的核心特性之一,通过@Autowired注解自动装配bean的依赖。 10. **RESTful Web服务**:如何使用Spring MVC创建符合REST原则的服务,如HTTP动词(GET、POST、PUT、DELETE)的映射。 在压缩包...

    spring-framework-4.2.0.RELEASE官方完整包加官方文档

    本文将围绕Spring Framework 4.2.0.RELEASE这一版本,深入解析其特性、核心概念以及使用方法。 首先,4.2.0.RELEASE是Spring框架的一个稳定版本,它在4.x系列中引入了多项改进和新特性。这些改进旨在提升性能,增强...

    spring-framework-5.2.25.RELEASE.tar.gz

    《Spring框架5.2.25.RELEASE源码解析》 Spring Framework是Java开发领域中最受欢迎的开源框架之一,以其模块化、松耦合和强大的功能特性,深受开发者喜爱。5.2.25.RELEASE作为Spring框架的一个稳定版本,为开发者...

Global site tag (gtag.js) - Google Analytics