`
XTU_xiaoxin
  • 浏览: 237204 次
  • 性别: 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容器中装配Bean详解

    主要介绍了spring在IoC容器中装配Bean详解,具有一定借鉴价值,需要的朋友可以参考下

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

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

    详解Spring框架---IOC装配Bean

    本篇文章主要介绍了详解Spring框架---IOC装配Bean,提供了三种方式实例化Bean,具有一定的参考价值,有兴趣的可以了解一下。

    Spring bean的实例化和IOC依赖注入详解

    主要介绍了Spring bean的实例化和IOC依赖注入详解,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

    跟我学spring3(1-7)

    【第六章】 AOP 之 6.5 AspectJ切入点语法详解 ——跟我学spring3 【第六章】 AOP 之 6.6 通知参数 ——跟我学spring3 【第六章】 AOP 之 6.7 通知顺序 ——跟我学spring3 【第六章】 AOP 之 6.8 切面实例化模型 ...

    Spring注解——@Profile详解

    Spring中的Profile功能可以理解为我们在Spring容器中所定义的Bean的逻辑组名称,只有当这些Profile被激活的时候,才会将Profile中所对应的Bean注册到Spring IoC容器中。 举个更具体的例子,我们以前所定义的Bean,当...

    关于SpringBoot获取IOC容器中注入的Bean(推荐)

    本文通过实例代码给大家详解了springboot获取ioc容器中注入的bean问题,非常不错,具有一定的参考借鉴价值,需要的朋友参考下吧

    JAVA spring 系列案例50个和学习资料

    Spring系列第7篇:依赖注入之手动注入Spring系列第8篇:自动注入(autowire)详解,高手在于坚持Spring系列第9篇:depend-on到底是干什么的?Spring系列第10篇:primary可以解决什么问题?Spring系列第11篇:bean中...

    spring jar 包详解

    (2) spring-beans.jar 这个jar文件是所有应用都要用到的,它包含访问配置文件、创建和管理bean以及进行Inversion of Control / Dependency Injection(IoC/DI)操作相关的所有类。如果应用只需基本的IoC/DI支持,...

    JSP 中Spring Bean 的作用域详解

    JSP 中Spring Bean 的作用域详解 Bean元素有一个scope属性,用于定义Bean的作用域,该属性有如下五个值: 1&gt;singleton: 单例模式,在整个spring IOC容器中,单例模式作用域的Bean都将只生成一个实例。一般Spring...

    《精通Spring2.X企业应用开发详解》随书源码1-15章

    概述 第1章 Spring概述 第2章 快速入门 第2篇 Spring核心技术 第3章 IoC容器概述 第4章 在IoC容器中装配Bean 第5章 Spring容器高级主题 第6章 Spring AOP基础 第7章 基于@AspectJ和Schema的...

    Spring中Bean的讲解

    本文是Spring-Bean相关基础知识点,欢迎阅读,学习,一起进步。 初识Spring框架请参考:Spring框架基础 Spring-IOC框架请参考:IOC详解 Spring-AOP框架请参考:AOP详解 文章目录一.Bean的简介二.Bean相关配置三....

    跟我学spring3(1-7).pdf

    Spring概述2.1 IoC基础2.2 IoC 容器基本原理2.3 IoC的配置使用——跟我学Spring33.1 DI的配置使用3.2 循环依赖3.3 更多DI的知识 3.4 Bean的作用域 4.1 基础知识4.2 内置Resource实现4.3 访问Resource4.4 Resource...

    吴天雄--Spring笔记.doc

    IOC详解,Spring环境搭建,Spring创建Bean的三种方式,scope属性详解(包含单例设计模式),DI详解,Spring的几种注入方式,利用Spring简化Mybatis;第二天内容:AOP(AOP常用概念、Spring的三种aop实现方式、代理...

    spring杂谈 作者zhang KaiTao

    1.6 »Spring 之AOP AspectJ切入点语法详解(最全了,不需要再去其他地找了) 1.7 Spring开闭原则的表现-BeanPostProcessor扩展点-2 1.8 Spring3.1 对Bean Validation规范的新支持(方法级别验证) 1.9 Spring对事务...

    跟开涛学Spring

    1.1 【第二章】 IoC 之 2.3 IoC的配置使用——跟我学Spring3 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4 1.2 【第二章】 IoC 之 2.1 IoC基础 ——跟我学Spring3 . . . . . . . . . . . ...

    详解Spring的核心机制依赖注入

    详解Spring的核心机制依赖注入 对于一般的Java项目,他们都或多或少有一种依赖型的关系,也就是由一些互相协作的对象构成的。Spring把这种互相协作的关系称为依赖关系。如A组件调用B组件的方法,可称A组件依赖于B...

    JSP 开发之Spring Security详解

    它提供了一组可以在Spring应用上下文中配置的Bean,充分利用了Spring IoC(依赖注入,也称控制反转)和AOP(面向切面编程)功能,为应用系统提供声明式的安全访问控制功能,减少了为企业系统安全控制编写大量重复...

    《精通Spring2.X企业应用开发详解》16-19章

    概述 第1章 Spring概述 第2章 快速入门 第2篇 Spring核心技术 第3章 IoC容器概述 第4章 在IoC容器中装配Bean 第5章 Spring容器高级主题 第6章 Spring AOP基础 第7章 基于@AspectJ和Schema的...

Global site tag (gtag.js) - Google Analytics