Spring-XML配置文件(IOC实验总结)

1.概述

XML格式的容器信息管理方式是Spring提供的最为强大,支持最全面的方式。在之前的文章中,关于配置文件进行几个小实验,这篇文章将会进行总结。

2.设置配置文件

2.1 <beans>

所有使用XML文件进行配置信息加载的IOC容器,包括BeanFactory和ApplicationContext的所有XML相应实现,都使用统一的XML格式。从Spring2.0版本之后,Spring在继续保持向前兼容的前提下,既可以使用DTD方式的DOCTYPE进行配置文件格式的限定,又引入了基于XML Schema的文档声明。所以Spring2.0之后,可以使用如下的基于XSD的文档声明(实验2.1中的第二步编写配置文件):

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

所有注册到容器中的业务元素,在Spring中称为Bean。所以每个对象在XML中的映射也自然而然地对应一个叫做<bean>的元素。既然容器最终可以管理所有的业务对象,那么在XML中把这些叫做<bean>元素组织起来的,就叫做<beans>

<beans>是XML配置文件中最顶层的元素,它下面可以包括0个或1个<description>和多个<bean>以及<import>或者<alias>

<beans>作为所有<bean>的统帅,它拥有相应的属性对所辖的<bean>进行统一的默认行为设置,包括如下几个:

  • default-lazy-init:其值可以指定为true或者false。默认值为false。用来标志是否对所有的<bean>进行延迟初始化。
  • default-autowire:可以取值为no,byName,byType,constructor以及autodetect。默认值为no,如果使用自动绑定的话,用来标志全体bean使用哪一种默认绑定方式。
  • default-dependcy-check:可以取值为none,object,simple以及all,默认值为none,即不做依赖检查。
  • default-init-method:如果所管辖的bean按照某种规则,都有同样名称的初始化方法,可以在这里统一指定这个初始化方法名,而不用在每一个<bean>上都重复单独指定。
  • default-destroy-method:与default-init-method相对应,如果所管辖的bean有按照某种规则使用了相同名称的对象销毁方法,可以通过这个属性统一指定。

<description>:通过这个可以在配置文件中指定一些描述性的信息,通常情况下,这个元素是省略的。

<import>:通常情况下,可以根据模块功能或者层次关系,将配置信息分门别类地放到多个配置文件中。在想加载主要配置文件,并将主要配置文件所依赖的配置文件同时加载时,可以在这个主要配置文件中通过<import>元素对其所依赖的配置文件进行引用。

<alias>:可以通过这个元素为某些bean起一些外号。

2.2<bean>

实验2.1中的第二步编写配置文件,就对<bean>进行了设置,现在对其属性进行解释:

  • id属性:通常,每个注册到容器的对象都需要一个唯一标志将其与其他bean区分开来。通过id属性来指定当前注册对象的beanName是什么。实际上,并非任何情况下都需要指定每个<bean>的id,有些情况下,id可以省略,例如内部bean以及不需要根据beanName明确依赖关系的场合。
  • name属性:来指定<bean>的别名。与id属性相比,name可以使用id不能使用的一些字符,比如/。而且还可以通过逗号,空格或者冒号分割指定多个name。name的作用跟使用<alias>为id指定多个别名基本相同。
  • class属性:每个注册到容器的对象都需要<bean>元素的class属性指定其类型。在大部分情况下,该属性是必须的。仅在少数情况下是不需要指定的,如使用抽象配置模板的情况下。

2.2.1 为Bean赋值

实验2.1 就关于通过setter方法为bean属性赋值进行了实验。

实验2.3就关于通过构造器为bean属性赋值进行了实验。

实验2.5关于为各种属性(null,引用对象,集合类型)赋值进行了实验。

之前在这三个实验中可以看到,可以通过在<property>和<constructor-arg>这两个元素内部嵌套不同的元素,面来指定为当前对象注入数据或者某个对象的引用。下我们来详细进行讲解:

(1)<value>。可以通过value为主体对象注入简单的数据类型,不但可以指定String类型的数据,而且可以指定其他Java语言中的原始类型以及它们的包装器(wrapper)类型,比如int,Integer等。容器在注入的时候,会做适当的转换工作。也有简化形式,作为<bean>元素的属性身份。

(2)<ref>。使用ref来引用容器中的其他对象实例,可以通过ref的local,parent和bean属性来指定对象的beanName是什么。

  • local只能指定与当前配置的对象在同一配置文件的对象定义的名称(可以获得XML解析器的id约束验证支持)
  • parent只能指定位于当前容器的父容器中定义的对象引用。
  • bean基本上都可以,所以,通常情况下,直接使用bean来指定对象引用就可以了

(3)<idref>。如果要为当前对象注入所依赖对象的名称,而不是引用,那么通常情况下,使用<value>可以达到目的,但是使用<idref>更合适。因为使用idref,容器在解析配置的时候就可以帮你检查beanName是否存在,而不用等到运行时才发现这个beanName对应的对象实例不存在。

(4)内部<bean>。使用<ref>可以引用容器中独立定义的对象定义。但有时,可能我们依赖的对象只有一个当前对象引用,或者某个对象定义我们不想其他对象通过<ref>引用到它,这时候,可以使用内嵌的<bean>,将这个私有的对象定义仅局限在当前对象。

(5)<list>。对应注入对象类型为java.util.List及其子类或者数组类型的依赖对象。通过<list>可以有序地位当前对象注入以collection形式声明的依赖。<list>元素内部可以嵌套其他元素,并且可以是不同类型的。

(6)<set>。对应注入Java Collection中类型7java.util.Set或者其子类的依赖对象,是无序的。

(7)<map>。对应注入java.util.Map或者其子类型的依赖对象。与<list>使用数字下标来标识元素不同,映射可以通过指定的键来获取相应的值。对应<map>来说,可以内嵌任意多个<entry>,每一个<entry>都需要为其指定一个键和一个值。

  • 指定entry的键。可以使用<entry>的属性---key或者key-ref来指定键,也可以使用<entry>的内嵌元素<key>来指定键。在<key>的内部,可以使用以上提到的任何元素来指定键,从简单的<value>到复杂的Collection,都可以。
  • 指定entry的值。<entry>内部可以使用的元素,除了<key>用来指定键的,其他元素可以任意使用,来指定entry对应的值。如果对应的值只是简单的原始类型或者单一的对象引用,也可以直接使用<entry>的value或者value-ref这两个属性来指定。

(8)<props>。是特殊的map,该元素对应配置类型为java.util.Properties的对象依赖。Properties只能指定String类型的键和值。每个<props>可以嵌套多个<prop>,每个<prop>通过其key属性来指定键,在<prop>内部直接指定其所对应的值,内部没有任何元素可以使用,只能指定字符串,这个是由java.util.Properties的语意来决定的。

(9)<null/>。空元素。对于String类型来说,如果通过value以这样的方式指定注入,即<value></value>,那么,得到的结果是“”,而不是null。需要注入null,要使用<null/>。并非仅限String类型。

2.2.2 bean之间的依赖

(1)denpends-on。实验2.10就是关于bean之前依赖的实验。通常情况下,可以直接通过之前提到的元素,来显示指定bean之间的依赖关系。这样容器在初始化当前bean定义的时候,会根据这些元素所标记的依赖关系,首先实例化当前bean定义所依赖的其他bean定义,就是使用这个属性来指定的。

(2) autowire。实验3.5进行了基于XML的自动装配的实验。Spring还提供了根据bean定义的某些特点将互相依赖的某些bean直接绑定的功能。通过<bean>的autowire属性,可以指定当前bean定义采用某种类型的自动绑定模式,这样无需手工指定该bean定义的依赖关系。Spring提供可5中自动绑定模式:

  • no:容器默认的自动绑定模式,也就是不采用任何形式的自动绑定功能,完全依赖手工明确配置各个bean之间的依赖关系。
  • byName:按照类中声明的实例变量的名称,与XML配置文件中声明的bean定义的beanName的值进行匹配,相匹配的bean定义将被自动绑定到当前实例变量上。假设有所示的类定义:
public class F{

    private Bar b;
    ...
    //相应的setter方法
}

public Class Bar{
 ...
}

配置文件应该这样写:

<bean id="fBean" class="..." autowire="byName">
</bean>
<bean id="b" class="..Bar">
</bean>
  • byType:容器会根据当前bean定义类型,分析其对应的依赖对象类型,然后到容器管理的所有bean定义中寻找与依赖对象类型相同的bean定义,然后将找到的符合条件的bean自动绑定到当前bean定义。但是byType只能保证,在容器中只存在一个符合条件的依赖对象时候才会发挥最大的作用,如果存在多个相同类型的bean定义,只能采用手动明确配置。
  • constructor:byName和byType的自动绑定模式是针对property的自动绑定,而constructor类型则是针对构造方法参数的类型而进行的自动绑定,它同样是byType类型的绑定模式。不过,constructor是匹配构造方法的类型参数,而不是实例属性的类型。与byType模式类似,如果找到不止一个符合条件的bean定义,那么容器会返回错误。
public class F{

    private Bar b;
    public F(Bar arg)
    {   this.b=arg;
     }
    ...
}

相应配置:

<bean id="F" clss="...F" autowire="constructor"/>
<bean id="bar" class="..Bar></bean>
  • autodetect:这种模式时byType和constructor模式的结合体,如果对象拥有默认无参数的构造方法,容器会先考虑byType的自动绑定模式。否则会使用constructor模式。当然,如果通过构造方法注入绑定后还有其他属性没有绑定,容器也会使用byType对剩余对象属性进行自动绑定。

注意事项:

  • 手工明确的绑定关系总会覆盖自动绑定模式的行为。
  • 自动绑定只应用原生类型,String类型以及“Classes类型”以外的对象类型,对于“原生类型”,String类型和Classes类型,以及这些类型的数组应用自动绑定是无效的。

自动绑定的优点:

  • 某种程度上可以有效减少手动敲入配置信息的工作量。
  • 某些情况下,即使为当前对象增加了新的依赖关系,但只要容器中存在相应的依赖对象,就不需要更改任何配置信息。

自动绑定的缺点:

  • 自动绑定不如明确依赖关系一目了然。使用自动绑定,可能需要在类定义以及配置文件之间,甚至各个配置文件之间来回转换以取得相应的信息。
  • 某些情况下,自动绑定无法满足系统需要,甚至导致系统行为异常或者不可预知。根据类型byType匹配进行的自动绑定,如果系统中增加另一个相同类型的bean定义,那么系统就会奔溃;根据名字byName匹配进行的自动绑定,如果把原来系统中相同名称的bean定义类型换掉,就会造成问题。
  • 使用自动绑定,无法获得某些工具的良好支持。

(3)dependency-check。使用这个属性对其所依赖的对象进行最终检查。该功能主要与自动绑定结合使用,可以保证自动绑定完成后,最终确定每个对象所依赖的对象是否按照预期的那样被注入,不过可能无法细化到某种具体类型检查。基本上有如下四种类型的依赖检查:

  • none:不做依赖检查。默认情况下为此值。
  • simple:容器会对简单属性类型以及相关的collection进行依赖检查,对象引用类型的依赖除外。
  • object:只对对象引用类型依赖进行检查。
  • all:将simple与object结合。

2.2.4 延迟初始化

实验2.1中细节问题的第一个问题就讲了容器中的对象什么时候被创建。

延迟初始化lazy-init,主要可以针对ApplicationContext容器的bean初始化行为施加更多控制。ApplicationContext在容器启动的时候,就会马上对所有的“singleton的bean定义”进行实例化操作。通常这种默认行为时好的,因为如果系统有问题的话,可以在第一时间发现这些问题。有时候想改变某个或者某些bean定义在ApplicationContext容器中的默认实例化时机,就可以通过<bean>的lazy-init属性来控制这种初始化行为。

要注意的是,如果某非延迟初始化的bean定义依赖于lazy-init-bean,按照依赖决计的顺序,容器还是会首先实例化lazy-init-bean,然后再实例化后者。延迟初始化就会失败。

2.2.5 继承与模板

实验2.8进行了关于通过继承实现bean配置信息的重用的实验。

实验2.9进行了关于通过abstract属性创建一个模板bean的实验。

(1)parent属性。继承了父类定义的默认值,只需要将特定的属性进行修改,而不要全部重新定义一遍。

(2)abstract属性。声明为true时,说明这个bean不需要实例化,可以不指定class属性的场景之一。该bean定义只是一个配置模板,不对应任何对象。容器在初始化对象实例的收时候,不会关注将abstract属性声明为true的bean定义。

2.2.6 作用域

实验2.11进行了测试bean的作用域,分别创建单实例和多实例的bean的实验。

scope用来声明容器中的对象所应该处的限定场景或者说该对象的存活时间,即容器在对象进入其相应的scope之前,生成并装配这些对象,在该对象不再处于这些scope的限定之后,容器通常会销毁这些对象。配置中的bean定义可以看做是一个模板,容器会根据这个模板来构造对象,但是要根据这个模板创造多少对象实例,又该让这些构造完的对象实例存活多久,则由容器根据bean定义的scope语意来决定。

scope有以下取值:

(1)singleton:在Spring的IOC容器中只存在一个实例,所有对该对象的引用将共享这个实例。该实例从容器启动,并因为第一被请求而初始化之后,将一直存活到容器退出,也就是说,它与IOC容器几乎拥有相同的寿命。

(2)prototype:针对声明为拥有prototype scope的bean定义,容器在接到该类型对象的请求的时候,会每次都重新生成一个新的对象实例给请求方。虽然这种类型的对象的实例化以及属性设置等工作都是由容器负责的,但是只要准备完毕,并且对象实例返回给请求方之后,容器就不再拥有当前返回对象的引用,请发方需要自己负责当前返回对象的后继生命周期的管理工作,包括该对象的销毁。对于那些请求方不能共享使用的对象类型,应该将其bean定义的scope设置为property。

(3)request:Spring容器,即XmlWebApplicationContext会为每个HTTP请求创建一个全新的RequestProcessor对象供当前请求使用,当请求结束后,该对象实例的生命周期即告结束。假设同时有10个HTTP请求进来的时候,容器会分别针对这10个请求返回10个对象实例,且它们之间互不干扰。

(4)session:Spring对象会为每个独立的session创建属于它们的对象实例。拥有session scope的bean的实例具有比request scope的bean可能更长的实例。

(5)global session:只有应用在基于portlet的Web应用程序才有意义,它映射到portlet的global范围的session。如果在普通的基于Servlet的Web应用中使用了这个类型的scope,容器会将其作为普通的session类型的scope对待。

注意:后三个scope类型只适用Web应用程序,通常是与XMLWebApplicationContext共同使用。

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Spring-IOCSpring框架的核心部分之一,它是一种设计模式,全称为Inversion of Control(控制反转)。它通过将对象的创建、依赖关系的管理和对象的生命周期交给Spring容器来实现,从而降低了组件之间的耦合度,提高了代码的可重用性和可维护性。Spring-IOC的实现主要依靠Spring容器,Spring容器是Spring框架的核心,它负责创建、管理和装配Bean对象,其中Bean是Spring框架中最基本的组件。 Spring-IOC的实现主要有两种方式:BeanFactory和ApplicationContext。其中,BeanFactory是Spring-IOC的基本实现,而ApplicationContext是BeanFactory的子接口,提供了更多高级特性。ApplicationContext是Spring框架中最常用的IOC容器,它除了提供BeanFactory的所有功能外,还提供了更多的企业级特性,例如AOP、事务管理、国际化、事件传播等。 下面是一个简单的Spring-IOC的例子,假设我们有一个UserService接口和一个UserServiceImpl实现类,我们可以通过Spring-IOC容器来创建和管理UserServiceImpl对象: 1.定义UserService接口和UserServiceImpl实现类 ```java public interface UserService { void addUser(User user); } @Service public class UserServiceImpl implements UserService { @Override public void addUser(User user) { // 添加用户的具体实现 } } ``` 2.在Spring配置文件配置UserService实例 ```xml <bean id="userService" class="com.example.service.UserServiceImpl"/> ``` 3.在代码中获取UserService实例并使用 ```java ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); UserService userService = context.getBean("userService", UserService.class); User user = new User(); userService.addUser(user); ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值