Spring入门2. IoC中装配Bean

Spring入门2. IoC中装配Bean 20131125

前言:

         上一节学习了Spring在JavaProject中的配置,通过配置文件利用BeanFactory和ApplicationContext实现了IoC的功能。这一节进一步学习Ioc 中的Bean装配。在Spring容器中的Bean装配方式,配置文件的深入等等。

1.Spring配置文件的方式

         DTD格式 和Schema格式,推荐使用Schema格式.

         使用Schema格式的配置文件拥有自己的命名空间,文件格式如下:

<?xml version="1.0" encoding="UTF-8"?>

<beans

    xmlns="http://www.springframework.org/schema/beans"

    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

    xmlns:aop="http://www.springframework.org/schema/aop"

    xmlns:tx="http://www.springframework.org/schema/tx"

    xsi:schemaLocation="

        http://www.springframework.org/schema/beans

        http://www.springframework.org/schema/beans/spring-beans-3.2.xsd

        http://www.springframework.org/schema/aop

        http://www.springframework.org/schema/aop/spring-aop-3.2.xsd

        http://www.springframework.org/schema/tx

        http://www.springframework.org/schema/tx/spring-tx-3.2.xsd"

    default-lazy-init="true">

    <bean id="customer" class = "com.yang.model.Customer">

        <property name="userName" value="杨腾飞"/>

        <property name="password" value="12345"/>

        <property name="age" value = "21"/>

    </bean>

</beans>

2.Bean基本配置

    在Spring配置文件中配置一个bean的规范:

<bean id=beanId class = ClassNameWithPackage />

    一般情况之下,SpringIoC容器中的一个Bean对应配置文件中的一个<bean>,其中id对应的是Bean的名称,可以通过容器的getBean(String name)便可以获得对应的Bean

3.依赖注入的方式

    依赖注入(Dependency Injection,DJ)和反转控制(Inversion Of Control)是类似的概念。具体的含义就是:当某个Java实例需要另一个Java实例的时候,在传统的程序程序设计过程中,通常由调用者来创建被调用者的实例;但是在Spring中,这个创建的工作不在有调用者来完成,因此被称为反转控制;创建被调用者实例的工作实际上是Spring容器完成的,然后注入给调用者,因此被称为依赖注入。根据注入方式的不同,依赖注入有一下两种:

         设值注入:通过setter的方法注入到Bean的属性值或者是对象中;在Spring中大量的使用这种方法,因为其比较直观、简单。设值注入的方式需要类提供一个默认的无参构造方法,并且需要为对应的属性提供对应的setter方法。同时使用关键字property设值属性的值:

         <bean id = beanId class =  PackageName.ClassName>

                   <property name=propertyName value=Val/>

         </bean>

    构造注入:通过使用构造器来注入Bean属性值或者是依赖对象。这种方式可以确保一些必要的属性在Bean实例化的时候,就已经得到初始值,从而使Bean在实例话之后就可以直接使用。

    构造注入的方式和设值注入的方式有所不同。我们通过一个实例来说明通过构造注入的方式:

首先是Model的修改,因为是构造注入,所以我们需要有一个和参数类型相匹配的构造函数,同时因为添加了构造函数,就会覆盖原来默认的构造函数,所以我们需要显式的声明默认构造函数:

public Customer(){

        System.out.println("Customer() constructor");

    }

    public Customer(String name, String pwd, Integer age){

        this.userName = name;

        this.password = pwd;

        this.age = age;

    }

然后再bean中配置bean实例信息;

<bean id="customer2" class="com.yang.model.Customer">

        <constructor-arg type="java.lang.String">

            <value>追梦的飞飞</value>

        </constructor-arg>

        <constructor-arg type="java.lang.String">

            <value>45678</value>

        </constructor-arg>

        <constructor-arg type="java.lang.Integer">

            <value>23</value>

        </constructor-arg>

    </bean>

 

两种方式比较:

设值注入与传统的JavaBean写法相似,便于程序开发者理解,通过setter设值属性值比较直观;同时对于复杂的依赖关系,这种方式相比构造注入比较简洁。Spring在创建bean的时候,需要同时实例化其依赖的全部实例,导致性能下降,从而使用设值注入,可以避免这些问题;

构造注入可以在构造器中决定依赖关系的注入顺序,比如使用数据库的时候需要优先注入数据库连接;对于依赖关系无需变化的Bean,如果没有setter方法,所有依赖关系都是在构造函数中实现,后续代码不会对其产生影响,依赖关系仅仅在构造函数中,符合高内聚低耦合的规则。

随意推荐使用的是设置注入的方式,以构造注入的方式为辅,对于构造关系无需变化的注入尽量采用构造注入。

4.注入值得类型

    直接的字面值,就是我们之前使用的string和int等类型

    引用其他的bean:SpringIoC 容器中定义的Bean是可以相互引用的,IoC容器负责装配

    使用关键字ref

    <bean id= beanId class="Package".ClassName>

        <property name=propertyName>

            <ref bean =“beanName” />

        </property>

    </bean>

    或者可以简单的表示为

    <property name=propertyName ref=beanName/>

    集合值:在bean中使用的是List set map等等集合值得时候,使用<list> <set> <map> <props>设值集合属性的值。

<bean id="empl" class="com.yang.model.Employee">

        <property name="schools">

            <list>

                <value>中山大学</value>

                <value>河北衡水中学</value>

                <value>阜城县长城双语学校</value>

                <value>古城镇初级中学</value>

            </list>

        </property>

        <property name="equi">

            <map>

                <entry key="主机" value="联想"/>

                <entry key="显示器" value="三星"/>

            </map>

        </property>

        <property name="address">

            <props>

                <prop key="祖籍">河北衡水</prop>

                <prop key="居住地">广东广州</prop>

            </props>

        </property>

        <property name="work">

            <set>

                <value>软件工程师</value>

                <value>本科生</value>

            </set>

        </property>

    </bean>

5.Bean之间的关系

    Bean之间的关系有两种:继承和依赖

    继承关系:如果存在多个Bean存在相同的配置信息,Spring允许顶一个而一个父Bean,然后为其定义子bean,将自动继承其配置信息。Spring通过bean元素的parent属性为其指定父类的Bean。

    使用bean关键字的abstract表示该实例是抽象的,所以不能够在程序中实例化。

<bean id="abstractCustomer" class="com.yang.model.Customer" abstract="true">

        <property name="userName" value="杨腾飞"/>

        <property name="password" value="12345"/>

        <property name="age" value = "21"/>

    </bean>

   

    <bean id="customer3" parent="abstractCustomer">

        <property name="age" value="23"/>

    </bean>

    <bean id="customer4" parent="abstractCustomer">

        <property name="age" value="24"/>

    </bean>

   

    依赖关系:使用关键字ref建立bean之间的依赖关系,Spring负责管理这些bean之间的依赖关系,当实例化一个bean的时候,Spring保证高bean的所依赖的其他的bean已经初始化。如果不是直接的依赖关系的话,在bean中的属性depends-on可以指定前置依赖。

    <bean id = “customer” class=”com.yang.model.Customer”/>

    <bean id = “sailorder2” class=”com.yag.model.SailOrder” depends-on=”customer”/>

    这样就会指定依赖关系,在构造sailorder2的时候首先会去构造前面的bean。

    还可以使用标签<idref bean=”beanName”>

<bean id = beanName class= packageName.ClassName>

    <property name=”custId”>

        <idref bean=”beanName”>

</property>

</bean>

6.Bean作用域

    指定bean的作用域,这样对于bean会产生一定的影响。Spring支持五种bean作用域:

singleton:在每一个Spring容器中,一个Bean定义对应唯一的对象实例,并且bean是以单例的方式存在。只要ID相匹配,每一个获得的都是相同的实例。并且spring只会创建一个该bean的实例,这一个单例会被存储到单例缓存中(singleton cache)中,并且所有针对该bean的访问请求,都返回的同一个缓存中的实例。

    <bean id=beanId class="ClassName" scope=”singleton”></bean>

prototype:一个Bean定义对应多个实例对象,每一次调用getBean()就会创建一个新的Bean实例。容器负责跟踪bean实例的状态,维护bean的生命周期的行为。如果一旦一个Bean被设置成为prototype作用域,每一次请求Bean的id,就会生成一个新的bean实例。

    当bean不指定作用域的时候,默认会使用singleton作用域。Java在创建实例的时候,需要申请内存,实例不在使用的时候,还可能进行垃圾回收,这些工作都会导致比较大的系统开销,因此使用prototype的代价是比较大的,而singleton则是对象的复用,所以尽量避免使用prototype作用域。

request这是在HTTP请求中使用的,一个bean对应一个实例,级每一次HTTp请求都会生成各自的bean实例,作用域仅仅是在基于Web的Spring ApplicationContext下面有效。

session作用域是在一个HTTP Session,一个bean对应一个实例,也是仅仅在Web的Spring的ApplicationContext下面有效。

global session:全局的HttpSession中有效,也是在Web的Spring 的ApplicationContext下面有效。

7.自动装配

    SpringIoC容器提供相互协作的Bean自动装配机制,可以自动让Spring通过检查BeanFactory中的内容,来替开发人员指定Bean的依赖关系。由于autoware可以针对单个Bean进行设置,因此可以让有些bean使用autoware,有些不采用。Autoware的方便之处在于减少或者消除对属性或构造器的设置,简化配置文件。

    在Spring配置文件中,autoware一共有五种类型,可以在bean元素中使用autoware属性设置

    no:默认属性,表明不适用自动装配机制,必须使用<ref>显式的指出bean之间的依赖关系,这样可以是配置更加灵活和清晰,对于较大的部署配置,推荐使用这一种方式。

    byName:根据属性名称自动装配,此选项将检查容器并且根据名字查找和属性完全一致的bean,将其自动装配。例如bean中使用了autoware为byName,而该bean包含master属性,同时提供了setter方法,Spring就会查找属性名称是master的bean定义,装配master属性;

    byType:容器中存在一个和指定属性类型相同的bean,那么该属性会自动装配

    constructor:应用于构造函数的参数,如果在容器中没有找到和构造函数参数一致的bean,会抛出异常;

    autodetect:由框架本身决定使用哪一种方式。

 

YangTengfei

2013.11.25

原文地址:https://www.cnblogs.com/hbhzsysutengfei/p/3473166.html