首先,要明白,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技术,而且可以学学高手的编码规范以及重构技术。
分享到:
相关推荐
Spring为IOC容器注入Bean的五种方式详解 Spring 框架中,IOC(Inverse of Control,控制反转)容器是核心组件之一,用于管理 Bean 的生命周期。在 Spring 中,IOC 容器可以通过五种方式来注入 Bean,本文将对这五...
### Spring IoC与注解依赖注入详解 #### 一、Spring框架简介 Spring框架是由Rod Johnson创建的一个开源项目,最初是为了解决企业级应用开发中的复杂性问题而诞生的。Spring框架的核心特性包括IoC(Inversion of ...
**Spring Ioc 实现原理详解** Spring Ioc(Inversion of Control,控制反转)是Spring框架的核心特性之一,它改变了传统应用程序中对象的创建和管理方式。在传统的软件设计中,对象的创建和依赖关系的维护通常由...
### Spring_IOC详解:深入探索Spring框架的IOC容器原理 #### 引言 Spring框架作为Java企业级应用开发的基石,其核心组件之一便是IOC(Inverse of Control)容器。IOC容器负责管理应用程序中的对象及其依赖关系,...
Spring 框架系列(8)- Spring IOC 实现原理详解之 Bean 实例化(生命周期、循环依赖等) 本文主要研究 Spring 框架中 Bean 的实例化过程,包括 Bean 的生命周期和循环依赖问题的解决方案。在 Spring 框架中,Bean ...
Spring 在 IoC 容器中装配 Bean 详解 Spring 框架中的 IoC 容器是一个核心组件,它提供了 Bean 的装配、管理和依赖注入等功能。在 Spring 框架中,IoC 容器是 Bean 的容器,负责创建、管理和装配 Bean。在本文中,...
【Spring 框架与控制反转 (IOC) 知识详解】 Spring 框架是 Java Web 开发中广泛使用的轻量级框架,其核心特性是控制反转 (IOC) 和依赖注入 (DI)。控制反转是指将对象的创建权从应用程序代码转移到框架,即不再由...
**Spring Ioc 注入详解** Spring 框架的核心特性之一就是依赖注入(Dependency Injection,简称DI),也常被称为控制反转(Inversion of Control,IoC)。它是一种设计模式,可以减少代码之间的耦合,提高系统的可...
Spring 框架系列(7)- Spring IOC 实现原理详解之 IOC 初始化流程 本文将详细解释 Spring 框架中的 IOC(Inversion of Control,控制反转)实现原理之 IOC 初始化流程。IOC 是一种软件设计模式,用于将软件系统中...
**Spring IoC 框架详解** Spring框架是Java开发中的一个核心组件,它提供了许多功能,其中最重要的一项就是Inversion of Control(IoC),也称为Dependency Injection(DI)。IoC容器是Spring的核心,它负责管理...
2. **spring-beans.jar**:这个jar提供了bean的定义、创建和管理,以及IoC/DI的核心实现。它是所有Spring应用的基础,无论应用大小,都需要这个jar。 3. **spring-aop.jar**:AOP(面向切面编程)是Spring的一个...
Spring 框架的IoC(Inversion of Control,控制反转)实现原理是其核心特性之一,它使得组件之间的依赖关系不再由代码直接管理,而是交由容器负责。本篇文章将详细探讨Spring IoC的体系结构设计,以及如何实现这些...
**Spring的IOC原理详解** **一、IoC理论背景** 在面向对象的软件设计中,对象间的耦合是不可避免的,它们通过相互合作实现业务逻辑。这种耦合就像机械手表中的齿轮,彼此啮合共同完成任务。随着软件系统规模的扩大...
#### 一、Spring与IoC概念详解 ##### 1. 控制反转(IoC) - **定义**:控制反转(Inversion of Control, IoC)是一种设计原则,用于减少计算机代码之间的耦合度。在这种模式下,组件之间通过容器来建立相互间的...
**Spring-IOC实例详解** Spring框架是Java开发中不可或缺的一部分,尤其在企业级应用中,其Inversion of Control(IoC)容器是其核心特性之一。IoC,也被称为依赖注入(Dependency Injection,DI),是一种设计模式...