zoukankan      html  css  js  c++  java
  • spring实战一:装配bean之注入Bean属性

    内容参考自spring in action一书。

    创建应用对象之间协作关系的行为通常称为装配,这也是依赖注入的本质。

    1. 创建spring配置

    spring是一个基于容器的框架。如果没有配置spring,那么它就是一个空的容器,所以需要配置spring来告诉容器它需要加载哪些Bean和如何装配这些bean,这样才能确保它们能够彼此协作。

     从spring3.0开始,spring容器提供了两种配置bean的方式。第一种是传统上的使用一个或多个XML文件作为配置文件。第二种提供了基于java注解的配置方式。

    先说XML文件的配置方式:

    在XML文件中声明Bean时,Spring配置文件的根元素是来源于Spring Beans命名空间所定义的<beans>元素。下面是一个典型的Spring XML配置文件。

    <?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-3.0.xsd">
    <!-- Bean declarations go here -->
    </beans>

    在<beans>元素内可以放置所有的Spring配置信息,包括<bean>元素的声明。但是beans的命名空间并不是唯一的Spring命名空间。Spring的核心框架自带了10个命名空间配置。如下所示:

    2. 注入bean属性

    spring注入bean属性有三种方式,常用的有两种,第一种是通过构造器注入。第二种是通过Setter注入。

    第一种,通过构造器注入:

    先看最简单的构造器注入方式,通过默认构造函数进行注入。

        <bean id="duke" class="com.pcitc.springInAction.Juggler" />

    2.1.1 通过构造器注入简单值:

    现在进行按需实例化,不走默认的构造方法:

    <bean id="duke" class="com.pcitc.springInAction.Juggler">
            <constructor-arg value="15" />
        </bean>

    总结:在构造bean的时候可以使用 <constructor-arg>元素来告诉spring额外的信息。如果不配置 <constructor-arg>元素,那么spring将使用默认的构造方法,上面配置了 <constructor-arg>的value属性设置为15,Spring将调用Juggler的另一个构造方法。

    2.1.2 通过构造器注入对象引用:

    <bean id="sonnet29" class="com.pcitc.springInAction.Sonnet29" />
     <bean id="poeticDuke" class="com.pcitc.springInAction.PoeticJuggler">
            <constructor-arg value="15" />
            <constructor-arg ref="sonnet29" />
        </bean>

    总结: <constructor-arg ref="sonnet29" />,把bean引用传递给构造器,当spring碰到sonnet29和duke的声明时,它所执行的逻辑本质上和下面的java代码相同:

    Poem sonnet29 = new Sonnet29();
    Performer duke = new PoeticJuggler(15, sonnet29);

    通过工厂方法创建Bean:

    假如想声明的Bean没有一个公开的构造方法,那怎么办呢?方法是通过工厂方法创建bean。

    有时候静态工厂方法是实例化对象的唯一方法。Spring支持通过<bean>元素的factory-method属性来装配工厂创建的bean。

    定义一个单例类:

    package com.pcitc.springInAction;
    
    public class Stage {
        private Stage() {
        }
    
        private static class StageSingletonHolder {
            static Stage instance = new Stage();
        }
    
        public static Stage getInstance() {
            return StageSingletonHolder.instance;
        }
    }

    Stage类没有一个公开的构造方法,这时候只能通过Spring的factory-method属性调用一个指定的静态方法,从而代替构造方法来创建一个类的实例。

    在Spring配置文件下这样来声明该bean

    <bean id="theStage" class="com.pcitc.springInAction.Stage"
            factory-method="getInstance" />

    第二种,通过Setter方法注入:

    通常javabean的属性都是私有的,同时拥有一组存取器方法,以setXXX和getXXX形式存在.spring可以借助属性的set方法来配置属性的值,以实现setter方法注入。

    简单说明:

    2.2.1 注入简单值的方式:

    <bean id="kenny"
    class="com.springinaction.springidol.Instrumentalist">
    <property name="song" value="Jingle Bells" />
    </bean>

    在spring配置文件中,一旦Instrumentalist被实例化,<peoperty>元素会指示Spring调用setSong方法将song属性的值设置为"Jingle Bells"。需要说明的是value值的类型不基于String类型,也可以是数值类型和boolean类型,spring会根据属性值的类型进行自动转换。

    2.2.2 通过Setter注入对象引用:

    <bean id="kenny2"
    class="com.springinaction.springidol.Instrumentalist">
    <property name="song" value="Jingle Bells" />
    <property name="instrument" ref="saxophone" />
    </bean>

    注入内部bean:

    <bean id="kenny"
    class="com.springinaction.springidol.Instrumentalist">
    <property name="song" value="Jingle Bells" />
    <property name="instrument">
    <bean class="org.springinaction.springidol.Saxophone" />
    </property>
    </bean>

    内部bean是通过直接声明一个<bean>元素作为<property>元素的子节点而定义的,内部bean并限于setter注入,还可以把内部bean装配到构造方法的入参中,如下所示:

    <bean id="duke"
    class="com.springinaction.springidol.PoeticJuggler">
    <constructor-arg value="15" />
    <constructor-arg>
    <bean class="com.springinaction.springidol.Sonnet29" />
    </constructor-arg>
    </bean>

    在这里,Sonnet29的一个实例将作为内部bean被创建,并作为参数传递给PoeticJuggler的构造器。

    总结:需要注意的是内部Bean没有ID属性。虽然为内部bean配置一个ID属性是合法的,但是完全没有必要,因为永远不会通过名字来引用内部bean。这也突出了使用内部bean的最大缺点:它们不能被复用。内部bean仅适用于一次注入,而且也不能被其他bean所引用,而且某种程度上还会影响Spring XML配置的可读性。

    3. 使用Spring的命名空间p装配属性

    Spring的命名空间p提供了另外一种Bean属性的装配方式,命名空间的schema URI为

    http://www.springframework.org/schema/p.如果想使用命名空间p,只需要在Spring的XML配置中增加如下一段声明:

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:p="http://www.springframework.org/schema/p"
    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-3.0.xsd">

    使用方式如下:

    <bean id="kenny" class="com.springinaction.springidol.Instrumentalist"
    p:song = "Jingle Bells"
    p:instrument-ref = "saxophone" />

    p:song属性的值被设置为"Jingle Bells",将使用该值装配bean属性。p:instrument-ref属性的值被设置为"saxophone",将使用一个ID为saxophone的Bean引用来装配instrument属性。-ref后缀作为一个标识来告诉Spring应该装配一个引用而不是字面值。

    4. 装配集合元素

    上面Spring的几种配置方式都只能配置简单属性值和引用其他bean的属性,当bean的属性值的类型是集合时只能使用集合的配置方式,Spring提供了四种类型的集合配置方式:

    当装配类型为数值或者java.util.Collection任意实现的属性时,<List>和<Set>元素都可以用,其实属性实际定义的集合类型与选择<List>和<Set>没有任何关系。如果属性为任意的java.util.Collection类型时,这两个配置元素在使用时安全可以互换,不能因为属性为java.util.Set类型,就表示必须使用<set>元素来完成装配。使用<set>元素配置java.util.List类型的属性是可以的,只需要确保List中的每一个成员都必须是唯一的。

    <map>和<props>这两个元素分别对应java.util.Map和java.util.Properties。当需要由键-值对组成的集合时,这两种配置元素非常有用,这两种配置元素的关键区别在于,<props>要求键和值都必须为String类型,而<map>允许键和值可以是任意类型。

    4.1 装配集合元素之装配List,Set和Array

    Java对instruments的声明如下:

    private Collection<Instrument> instruments;

    spring的配置文件配置如下:

    <bean id="hank"
    class="com.springinaction.springidol.OneManBand">
    <property name="instruments">
    <list>
    <ref bean="guitar" />
    <ref bean="cymbal" />
    <ref bean="harmonica" />
    </list>
    </property>
    </bean>

    <list>元素包含一个或多个值。<ref>元素用来定义Spring上下文中的其他bean的引用。当然还可以使用其他的Spring设置元素作为<list>的成员,包括<value>,<bean>和<null/>,实际上<list>还可以包含另外一个<list>作为其成员,形成多维列表。

    即使像下面的方式来配置instruments属性,<list>元素也一样有效:

    java.util.List<Instrument> instruments;或者Instrument[] instruments;

    同样有可以使用<set>元素来装配集合类型或者数组类型的属性:

    <bean id="hank"
    class="com.springinaction.springidol.OneManBand">
    <property name="instruments">
    <set>
    <ref bean="guitar" />
    <ref bean="cymbal" />
    <ref bean="harmonica" />
    <ref bean="harmonica" />
    </set>
    </property>
    </bean>

    4.2 装配集合元素之装配Map集合

    Java对instruments的声明如下:

    private Map<String, Instrument> instruments;

    spring的配置文件配置如下:

    <bean id="hank" class="com.springinaction.springidol.OneManBand">
    <property name="instruments">
    <map>
    <entry key="GUITAR" value-ref="guitar" />
    <entry key="CYMBAL" value-ref="cymbal" />
    <entry key="HARMONICA" value-ref="harmonica" />
    </map>
    </property>
    </bean>

    <map>元素声明了一个java.util.Map类型的值。每个<entry>元素定义Map的一个成员。key元素指定了entry的键,而value-ref属性定义了entry的值,并引用了spring上下文中的其他bean。<entry>元素还有两个属性分别可以用来指定entry的键和值。

    当键和值都不是String类型时,将键-值对注入到Bean属性的唯一方法就是使用<map>元素。

    4.3 装配集合元素之装配Properties集合

    如果所配置的Map的每一个entry的键和值都为String类型时,可以考虑使用java.util.Properties代替Map。Properties类提供了和Map大致相同的功能,但是它限定键和值必须是String类型。

    Java对instruments的声明如下:

    private Properties instruments;

    spring的配置文件配置如下:

    <bean id="hank" class="com.springinaction.springidol.OneManBand">
    <property name="instruments">
    <props>
    <prop key="GUITAR">STRUM STRUM STRUM</prop>
    <prop key="CYMBAL">CRASH CRASH CRASH</prop>
    <prop key="HARMONICA">HUM HUM HUM</prop>
    </props>
    </property>
    </bean>

    Properties集合的配置要点:<property>元素用于把值或Bean引用注入到Bean的属性中;<props>元素用于定义一个java.util.Properties类型的集合值;<prop>元素用于定义<props>集合的一个成员。

    4.4 装配空值

    如果需要把属性值设置为null值,那么可以显示的为该属性装配一个null值。显示的为属性装配null值将会覆盖自动装配的值。

    <property name="someNonNullProperty"><null/></property>
  • 相关阅读:
    easyui带file上传控件表达提交
    WebApi返回json
    同一个项目中使用MVC控制器和WebAPI控制器
    jquery disabled
    ITIL(Information Technology Infrastructure Library )
    jquery.formatDateTime
    sqlserver 表连接更新字段
    C#分页的总页数算法
    Angular入门教程三
    Angular入门教程二
  • 原文地址:https://www.cnblogs.com/longshiyVip/p/4574459.html
Copyright © 2011-2022 走看看