• Srping


    目录


    1 概述

    2 两种基本的依赖注入方式

        2.1 构造函数方式

        2.2 Setter方式

    3 其他依赖注入功能

        3.1 <ref/>标签引用不同范围的bean

        3.2 内部bean

        3.3 集合注入

        3.4 集合合并

        3.5 强类型集合注入

        3.6 null和空字符串

        3.7 p-namespace方式配置属性注入

        3.8 c-namespace方式配置构造函数参数注入

        3.9 嵌套属性注入

     

    1 概述


    这篇文章主要就是讲解Springbean之间依赖注入的方法,本文不讲原理,只涉及用法。 

    在实际项目中,我们常常需要在一个bean中引用另外一个bean,例如业务逻辑处理(service)层调用数据处理(dao)层。那么就有了依赖注入(Dependency Injection),简称DI

     

    2 两种基本的依赖注入方式


    Spring提供了2种基本方式让我们实现DI,分别是通过构造函数和setter方法。下面我们来一一介绍。

     

    2.1 构造函数方式

    实现方式如下:

    java代码:

    package x.y;
    public class Foo {
        public Foo(Bar bar, Baz baz) {
            // ...
        }
    }

    bean配置:

    <beans>
        <bean id="foo" class="x.y.Foo">
            <constructor-arg ref="bar"/>
            <constructor-arg ref="baz"/>
        </bean>
        
        <bean id="bar" class="x.y.Bar"/>
        <bean id="baz" class="x.y.Baz"/>
    </beans>

    Spring会检查bean之间的依赖关系,会先加载(初始化)被依赖的bean,在例子中,barbaz首先被加载,然后通过构造函数参数的形式注入到foo中。相信这个很好理解吧。

    除了支持bean的注入之外,Spring还支持常量的注入,如下:

    <bean id="exampleBean" class="examples.ExampleBean">
        <constructor-arg type="int" value="7500000"/>
        <constructor-arg type="java.lang.String" value="42"/>
    </bean>

    其中constructor-arg需要根据构造函数的顺序对应好(参数类型要匹配)。

    除了默认的顺序排序,我们还可以指定Index属性,来指定constructor-arg对应构造函数参数的位置:

    <bean id="exampleBean" class="examples.ExampleBean">
        <constructor-arg index="0" value="7500000"/>
        <constructor-arg index="1" value="42"/>
    </bean>

    另外还可以指定参数名称来对应指定构造函数参数,但是这种方式需要给类的构造函数加上 @ConstructorProperties注解

    <bean id="exampleBean" class="examples.ExampleBean">
        <constructor-arg name="years" value="7500000"/>
        <constructor-arg name="ultimateanswer" value="42"/>
    </bean>
    package examples;
    public class ExampleBean {
        // Fields omitted
        @ConstructorProperties({"years", "ultimateAnswer"})
        public ExampleBean(int years, String ultimateAnswer) {
            this.years = years;
            this.ultimateAnswer = ultimateAnswer;
        }
    }

    2.2 Setter方式

    实现方式如下:

    java代码:

    public class ExampleBean {
        private AnotherBean beanOne;
        private YetAnotherBean beanTwo;
        private int i;
        
        public void setBeanOne(AnotherBean beanOne) {
            this.beanOne = beanOne;
        }
        
        public void setBeanTwo(YetAnotherBean beanTwo) {
            this.beanTwo = beanTwo;
        }
        
        public void setIntegerProperty(int i) {
            this.i = i;
        }
    }

    bean配置:

    <bean id="exampleBean" class="examples.ExampleBean">
        <!-- setter injection using the nested <ref/> element -->
        <property name="beanOne">
            <ref bean="anotherExampleBean"/>
        </property>
        <!-- setter injection using the neater 'ref' attribute -->
        <property name="beanTwo" ref="yetAnotherBean"/>
        <property name="integerProperty" value="1"/>
    </bean>
    <bean id="anotherExampleBean" class="examples.AnotherBean"/>
    <bean id="yetAnotherBean" class="examples.YetAnotherBean"/>

    Spring在实例化bean之后,会将配置中property属性通过对应的setter方法将被引用对象设置到bean的属性中。同样的,被引用的bean会先于引用beanSpring加载实例化。

    属性的setter方法需要遵循java的标准,即set + 属性名(首字母改为大写)。

    在上面例子中

    <property name="beanTwo" ref="yetAnotherBean"/>

    还可以写成:

    <property name="beanTwo"/> 

        <idref bean="yetAnotherBean"/> 

    </property> 

    或者:

    <property name="beanTwo" value="yetAnotherBean"/>

    通过<idref/>标签,Spring会去查找容器中ID为指定值的bean。

     

    3 其他依赖注入功能


    3.1 <ref/>标签引用不同范围的bean

    之前我们所看到的例子都是bean引用了同一个Spring容器中的bean,Spring还支持bean引用同个XML配置文件中的bean,或者是父容器的bean。写法分别是:

    引用当前容器中的bean

    <ref bean="someBean"/>

    引用父容器中的bean

    <ref parent="someBean"/>

    引用当前XML中的bean

    <ref local="someBean"/>

     

    3.2 内部bean

    内部bean指的是在某个bean内部配置的bean。配置方式如下:

    <bean id="outer" class="...">
        <!-- instead of using a reference to a target bean, simply define the target bean inline -->
        <property name="target">
            <bean class="com.example.Person"> <!-- this is the inner bean -->
                <property name="name" value="Fiona Apple"/>
                <property name="age" value="25"/>
            </bean>
        </property>
    </bean>

    内部bean可以不用的idname属性

    3.3 集合注入

    除了注入基础类型和bean之外,我们还可以对bean中的集合属性进行注入,ListSetMapProperties分别对应配置中的<list/><set/><map/><props/>标签,配置方式如下:

     

    <bean id="moreComplexObject" class="example.ComplexObject">
        <!-- results in a setAdminEmails(java.util.Properties) call -->
        <property name="adminEmails">
            <props>
                <prop key="administrator">administrator@example.org</prop>
                <prop key="support">support@example.org</prop>
                <prop key="development">development@example.org</prop>
            </props>
        </property>
        <!-- results in a setSomeList(java.util.List) call -->
        <property name="someList">
            <list>
                <value>a list element followed by a reference</value>
                <ref bean="myDataSource" />
            </list>
        </property>
        <!-- results in a setSomeMap(java.util.Map) call -->
        <property name="someMap">
            <map>
                <entry key="an entry" value="just some string" />
                <entry key="a ref" value-ref="myDataSource" />
            </map>
        </property>
        <!-- results in a setSomeSet(java.util.Set) call -->
        <property name="someSet">
            <set>
                <value>just some string</value>
                <ref bean="myDataSource" />
            </set>
        </property>
    </bean>

    3.4 集合合并

    假设我们有一个bean collectionParent,collectionParent里有个Properties类型的属性config:

    <bean id="collectionParent" class="cn.com.willchen.test.di.CollectionMergeInject">
        <property name="config">
            <props>
                <prop key="url">localhost</prop>
                <prop key="port">8080</prop>
            </props>
        </property>
    </bean>

    这时,因为业务需要,我们可能有多种场景,需要用到不同的config,或者内容更多的config,假设port属性改了,而且需要多一个protocol属性,那么我们可以这么做:

    <bean id="collectionChild" parent="collectionParent">
        <property name="config">
            <!-- the merge is specified on the *child* collection definition -->
            <props merge="true">
                <prop key="protocol">http</prop>
                <prop key="port">9090</prop>
            </props>
        </property>
    </bean>

    collectionChild的配置通过parent属性继承collectionParent,再在config的props标签中加入merge="true"的属性,就可以实现将collectionParent中config的配置合并过来。

    实例化后collectionParent的config属性是{port=8080, url=localhost}
    collectionChild的config属性是{port=9090, url=localhost, protocol=http}

    注意,重复的元素会被覆盖。

    这里用的是Properties作为例子,同样的ListMapSet也可以,但是对于List略有不同,List是以链表形式出现的,是有序的,2List合并成1List后,parent List的元素肯定在child List元素之前。

    不同类型的集合之间不能合并,否则Spring会抛出异常。

     

    3.5 强类型集合注入

    假设我们的bean 类中属性定义的是一个强类型的集合如Map<Sring, Fload>Spring同样支持注入:

    public class Foo {
        private Map<String, Float> accounts;
        public void setAccounts(Map<String, Float> accounts) {
            this.accounts = accounts;
        }
    }

     

    <bean id="foo" class="x.y.Foo">
        <property name="accounts">
            <map>
                <entry key="one" value="9.99" />
                <entry key="two" value="2.75" />
                <entry key="six" value="3.99" />
            </map>
        </property>
    </bean>

    例中的9.992.753.99在注入属性前Spring会自动做类型转换,例子中转为Float类型。

     

    3.6 null和空字符串

    这个比较简单,没什么好说的,看例子:

    空字符串:

    <bean class="ExampleBean">
      <property name="email" value=""/>
    </bean>

    null

    <bean class="ExampleBean">
      <property name="email"><null/></property>
    </bean>

     

    3.7 p-namespace方式配置属性注入

    p-namespace方式是用于替换<property/>标签的另外一种简洁的写法,通常我们给一个bean注入属性是这么写的:

    <bean name="classic" class="com.example.ExampleBean">
        <property name="email" value="foo@bar.com"/>
    </bean>

    在Spring 2.0之后,我们可以这么写:

    <bean name="p-namespace" class="com.example.ExampleBean" p:email="foo@bar.com"/>
    </beans>

    如果我们的bean的属性引用了其他bean,我们可以这么写:

    <bean name="john-modern" class="com.example.Person" p:name="John Doe" p:spouse-ref="jane"/>
    
    <bean name="jane" class="com.example.Person">
          <property name="name" value="Jane Doe"/>
    </bean>

    p:spouse-ref中spouse是属性的名称,-ref表示引用了其他bean。

    但是在实际项目中,我们还是需要保证所有配置使用一种风格,要么<property/>要么p-namespace格式。

     

    3.8 c-namespace方式配置构造函数参数注入

    c-namespace方式是用于替换<constructor-arg/>标签的另外一种写法,通常定义一个bean的构造函数的参数是这么写的:

    <bean id="bar" class="x.y.Bar"/>
    <bean id="baz" class="x.y.Baz"/>
    
    <bean id="foo" class="x.y.Foo">
        <constructor-arg ref="bar"/>
        <constructor-arg ref="baz"/>
        <constructor-arg value="foo@bar.com"/>
    </bean>

    通过c-namespace我们可以这么写:

    <bean id="foo" class="x.y.Foo" c:bar-ref="bar" c:baz-ref="baz" c:email="foo@bar.com">

    写法和p-namespace类似,也就把p换成c而已。

    3.9 嵌套属性注入

    假设bean中有个属性A,属性A里有个属性B,那么我们也可以通过配置给A.B赋值:

    <bean id="foo" class="foo.Bar">
        <property name="fred.bob.sammy" value="123" />
    </bean>

    需要注意的是,父属性不能为空,如例子中 fred不能为nullfred.bob也不能为null,否则在注入的时候会抛出空指针异常。

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

  • 相关阅读:
    Android Logcat使用技巧
    SqlClient使用存储过程并获取输出参数的指
    内存调试的东西D/dalvikvm( 809 ): GC_CONCURRENT freed
    android 读写sd卡的权限设置
    Android中EditText的使用方法持續更新
    RSL编译方式的FLEX站点出现#2046错误
    从网络读取数据并动态的显示在ListView中
    LEFT JOIN INNER JOIN 效率比较
    使用Installshield2009 在IIS6部署Asp.net mvc 应用程序
    Installshield2009中使用osql.exe执行数据库脚本
  • 原文地址:https://www.cnblogs.com/ViviChan/p/4981443.html
Copyright © 2020-2023  润新知