`
XTU_xiaoxin
  • 浏览: 239934 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

一步一步学习spring(四)——Ioc之Bean的注入详解

阅读更多
   首先,要明白,ApplicationContext扩展了ResourceLoader,它和XmlBeanFactory不一样,在容器启动的时候,不需要向ApplicationContext传入Resource,只需传入Spring的资源文件名,ApplicationContext会自动加载资源文件名对应的Resource。并且你可以同时配置多个资源文件一起传给ApplicationContext。
    
   在容器启动时,开始了容器中Bean的注入过程,具体详细注入过程,网上一大堆,为大家推荐个java eye中比较经典的IOC注入分析吧,网址是 :
  http://www.iteye.com/wiki/Spring-source/1226-Spring源代码解析(一):IOC容器
  
   在此,我主要给大家分析下在对资源文件中属性Bean的详细解析过程。
   spring中xml资源的解析,主要是由XmlBeanDefinitionReader完成,该类是在ApplicationContext容器启动时初始化的。解析的详细过程是BeanDefinitionParserDelegate代理完成的。
  
  BeanDefinitionParserDelegate中parseBeanDefinitionElement方法:
 
 
       /**
	 * Parse the bean definition itself, without regard to name or aliases. May return
	 * <code>null</code> if problems occured during the parse of the bean definition.
	 */
	public AbstractBeanDefinition parseBeanDefinitionElement(
			Element ele, String beanName, BeanDefinition containingBean) {
       /*
        * parserState是一个栈,里面只能存放ParseState.Entry类型的元素,所以,要想将String类型的beanName存入栈中,\
        * 必须将beanName封装成Entry元素
        */
		this.parseState.push(new BeanEntry(beanName));

		String className = null;
		if (ele.hasAttribute(CLASS_ATTRIBUTE)) {
			className = ele.getAttribute(CLASS_ATTRIBUTE).trim();
		}

		try {
			String parent = null;
			if (ele.hasAttribute(PARENT_ATTRIBUTE)) {
				parent = ele.getAttribute(PARENT_ATTRIBUTE);
			}
			/*
			 * 其实就是new一个BeanDefinition实例,并赋值此BeanDefinition的className以及parent属性值
			 */
			AbstractBeanDefinition bd = createBeanDefinition(className, parent);

			/*
			 * 对"<id="" name="" scope="" ..>"配置形式进行解析,解析出该Bean的一些生命周期、
			 * 是否延迟加载、自动装配方式等属性值,并且赋值给上面生成的BeanDefinition实例
			 */
			parseBeanDefinitionAttributes(ele, beanName, containingBean, bd);
			//解析Bean的"<description ../>"属性
			bd.setDescription(DomUtils.getChildElementValueByTagName(ele, DESCRIPTION_ELEMENT));
            
			parseMetaElements(ele, bd);
			//解析"<look-up ..>"形式的配置,得出的值存入的先前生成的Beandefinition的methoOverrides属性中
			parseLookupOverrideSubElements(ele, bd.getMethodOverrides());
			//解析"<replace ..>"形式的配置,得出的值存入的先前生成的Beandefinition的methoOverrides属性中
			parseReplacedMethodSubElements(ele, bd.getMethodOverrides());
            
			/*
			 * spring中的Ioc注入有三种方式:构造方法注入、set方法注入和接口注入,以下则为
			 * 几种注入方式的代码
			 */
			
			//构造方法注入处理
			parseConstructorArgElements(ele, bd);
			//set方法注入的处理(比较常用的注入)
			parsePropertyElements(ele, bd);
			parseQualifierElements(ele, bd);

			bd.setResource(this.readerContext.getResource());
			bd.setSource(extractSource(ele));

			return bd;
		}
		catch (ClassNotFoundException ex) {
			error("Bean class [" + className + "] not found", ele, ex);
		}
		catch (NoClassDefFoundError err) {
			error("Class that bean class [" + className + "] depends on not found", ele, err);
		}
		catch (Throwable ex) {
			error("Unexpected failure during bean definition parsing", ele, ex);
		}
		finally {
			this.parseState.pop();
		}

		return null;
	}


下面,将分析下set注入形式的解析处理,该处理是parseBeanDefinitionElement方法中完成的,具体如下:

/**
	 * Parse property sub-elements of the given bean element.
	 */
	public void parsePropertyElements(Element beanEle, BeanDefinition bd) {
		NodeList nl = beanEle.getChildNodes();
		for (int i = 0; i < nl.getLength(); i++) {
			Node node = nl.item(i);
			if (node instanceof Element && DomUtils.nodeNameEquals(node, PROPERTY_ELEMENT)) {
				//解析主要方法
				parsePropertyElement((Element) node, bd);
			}
		}
	}

 
  parsePropertyElement(Element ele, BeanDefinition bd)方法代码如下:
 
   /**
	 * Parse a property element.
	 */
	public void parsePropertyElement(Element ele, BeanDefinition bd) {
		//解析<proiperty name=..>中name属性值
		String propertyName = ele.getAttribute(NAME_ATTRIBUTE);
		if (!StringUtils.hasLength(propertyName)) {
			error("Tag 'property' must have a 'name' attribute", ele);
			return;
		}
		this.parseState.push(new PropertyEntry(propertyName));
		try {
			//如果该BeanDefinition中已经存在了一个与此name相同的属性值,则抛出异常
			if (bd.getPropertyValues().contains(propertyName)) {
				error("Multiple 'property' definitions for property '" + propertyName + "'", ele);
				return;
			}
			//解析该propertyName对应的值,也许只是一个普通的string,也许是个List列表,也许是该BeanDefinition依赖的一个Bean(对应"ref="形式的配置)
			Object val = parsePropertyValue(ele, bd, propertyName);
			//封装成PropertyValue
			PropertyValue pv = new PropertyValue(propertyName, val);
			//解析原始元素
			parseMetaElements(ele, pv);
			pv.setSource(extractSource(ele));
			/*
			 * 将解析完成的PropertyValue存入该BeanDefinition的PropertyValues中,
			 * 有两个作用: 1.容器启动后,加载该BeanDefinition对应的Bean时,需要设置该Bean的属性值
			 *            2.避免一个BeanDefiniton有多个相同的propertyName
			 */
			bd.getPropertyValues().addPropertyValue(pv);
		}
		finally {
			this.parseState.pop();
		}
	}

   都说程序员学习三部曲:what how why. 其实,我们在知道使用、知道配置spring的时候,我们应该还有尽自己最大努力做到 why。知其然,也要知其所以然。
分析源码是痛苦的,但对于初级程序员来说,收获也是巨大的,我们不仅可以更深一层次的掌握java技术,而且可以学学高手的编码规范以及重构技术。

2
1
分享到:
评论

相关推荐

    Spring为IOC容器注入Bean的五种方式详解

    Spring为IOC容器注入Bean的五种方式详解 Spring 框架中,IOC(Inverse of Control,控制反转)容器是核心组件之一,用于管理 Bean 的生命周期。在 Spring 中,IOC 容器可以通过五种方式来注入 Bean,本文将对这五...

    Spring Ioc 注解 依赖注入

    ### Spring IoC与注解依赖注入详解 #### 一、Spring框架简介 Spring框架是由Rod Johnson创建的一个开源项目,最初是为了解决企业级应用开发中的复杂性问题而诞生的。Spring框架的核心特性包括IoC(Inversion of ...

    springIoc实现原理

    **Spring Ioc 实现原理详解** Spring Ioc(Inversion of Control,控制反转)是Spring框架的核心特性之一,它改变了传统应用程序中对象的创建和管理方式。在传统的软件设计中,对象的创建和依赖关系的维护通常由...

    Spring_IOC详解.pdf

    ### Spring_IOC详解:深入探索Spring框架的IOC容器原理 #### 引言 Spring框架作为Java企业级应用开发的基石,其核心组件之一便是IOC(Inverse of Control)容器。IOC容器负责管理应用程序中的对象及其依赖关系,...

    Spring框架系列(8) - Spring IOC实现原理详解之Bean实例化(生命周期,循环依赖等).doc

    Spring 框架系列(8)- Spring IOC 实现原理详解之 Bean 实例化(生命周期、循环依赖等) 本文主要研究 Spring 框架中 Bean 的实例化过程,包括 Bean 的生命周期和循环依赖问题的解决方案。在 Spring 框架中,Bean ...

    spring在IoC容器中装配Bean详解

    Spring 在 IoC 容器中装配 Bean 详解 Spring 框架中的 IoC 容器是一个核心组件,它提供了 Bean 的装配、管理和依赖注入等功能。在 Spring 框架中,IoC 容器是 Bean 的容器,负责创建、管理和装配 Bean。在本文中,...

    spring_ioc.docx

    【Spring 框架与控制反转 (IOC) 知识详解】 Spring 框架是 Java Web 开发中广泛使用的轻量级框架,其核心特性是控制反转 (IOC) 和依赖注入 (DI)。控制反转是指将对象的创建权从应用程序代码转移到框架,即不再由...

    SpringIoc注入

    **Spring Ioc 注入详解** Spring 框架的核心特性之一就是依赖注入(Dependency Injection,简称DI),也常被称为控制反转(Inversion of Control,IoC)。它是一种设计模式,可以减少代码之间的耦合,提高系统的可...

    Spring框架系列(7) - Spring IOC实现原理详解之IOC初始化流程.doc

    Spring 框架系列(7)- Spring IOC 实现原理详解之 IOC 初始化流程 本文将详细解释 Spring 框架中的 IOC(Inversion of Control,控制反转)实现原理之 IOC 初始化流程。IOC 是一种软件设计模式,用于将软件系统中...

    maven-spring-ioc

    **Spring IoC 框架详解** Spring框架是Java开发中的一个核心组件,它提供了许多功能,其中最重要的一项就是Inversion of Control(IoC),也称为Dependency Injection(DI)。IoC容器是Spring的核心,它负责管理...

    Spring——jar详解

    2. **spring-beans.jar**:这个jar提供了bean的定义、创建和管理,以及IoC/DI的核心实现。它是所有Spring应用的基础,无论应用大小,都需要这个jar。 3. **spring-aop.jar**:AOP(面向切面编程)是Spring的一个...

    Spring框架系列(6) - Spring IOC实现原理详解之IOC体系结构设计.doc

    Spring 框架的IoC(Inversion of Control,控制反转)实现原理是其核心特性之一,它使得组件之间的依赖关系不再由代码直接管理,而是交由容器负责。本篇文章将详细探讨Spring IoC的体系结构设计,以及如何实现这些...

    Spring的IOC原理

    **Spring的IOC原理详解** **一、IoC理论背景** 在面向对象的软件设计中,对象间的耦合是不可避免的,它们通过相互合作实现业务逻辑。这种耦合就像机械手表中的齿轮,彼此啮合共同完成任务。随着软件系统规模的扩大...

    Spring - 2 IoC

    #### 一、Spring与IoC概念详解 ##### 1. 控制反转(IoC) - **定义**:控制反转(Inversion of Control, IoC)是一种设计原则,用于减少计算机代码之间的耦合度。在这种模式下,组件之间通过容器来建立相互间的...

    Spring-IOC实例

    **Spring-IOC实例详解** Spring框架是Java开发中不可或缺的一部分,尤其在企业级应用中,其Inversion of Control(IoC)容器是其核心特性之一。IoC,也被称为依赖注入(Dependency Injection,DI),是一种设计模式...

Global site tag (gtag.js) - Google Analytics