spring的依賴注入

spring與IoC

IoC:控制反轉,將由代碼操縱的對象控制權,交給第三方容器,反轉給第三方容器。這種對象依賴的關係管理方式,稱做IoC。IoC是一個思想,概念。比較 著名的兩種方式:spring

  1. DL(Dependency Lookup)依賴查找,典型的是JNDI。java名稱與服務接口。
  2. DI(Dependency Injection)依賴注入。是目前最優秀的接耦合方式。典型應用spring。

spring的DI

依賴注入,即:爲屬性賦值。數組

xml實現

1)設值注入

底層調用屬性的setter方法進行賦值,因此實體類屬性必定要有setter方法。dom

<bean id="student" class="com.abc.di01.Student">
    <property name="age" value="20"/>
    <property name="name" value="張三"/>
    <property name="school" ref="mySchool"/>
</bean>

使用property標籤給對應屬性賦值,或者使用"ref"指定一個引用類型;
ide

首先調用無參數構造器生成對象。而後調用setter方法給對象屬性賦值。若是定義的有參數的構造器,則須要添加一個無參數的構造器,以方便其建立對象。this

2)構造注入

底層調用帶參數的構造器。idea

<!--直接給對應的構造方法參數賦值-->
<bean id="student" class="com.abc.di02.Student">
    <constructor-arg name="age" value="20"/>
    <constructor-arg name="name" value="李四"/>
    <constructor-arg name="school" ref="mySchool"/>
</bean>
<!--使用索引方式賦值-->
<bean id="student" class="com.abc.di02.Student">
    <constructor-arg index="0" value="李四"/>
    <constructor-arg index="1" value="20"/>
    <constructor-arg index="2" ref="mySchool"/>
</bean>
<!--直接省略索引下標,進行賦值-->
<bean id="student" class="com.abc.di02.Student">
    <constructor-arg value="李四"/>
    <constructor-arg value="20"/>
    <constructor-arg ref="mySchool"/>
</bean>

使用 標籤,添加屬性的值便可。
code

中index的使用按照構造參數的順序進行賦值(第二種)。也能夠將索引的標籤省略掉(第三種)。
component

在實際使用中仍是使用name-value這種,看上去比較直觀清晰。xml

3)命名空間注入

兩種:

  1. p命名空間(property)注入:setter賦值
  2. c命名空間(constructor)注入:構造方法賦值(注意寫無參構造方法)

實際上底層依然調用的是setter和構造器方法。

首先須要引用約束:

xmlns:p="http://www.springframework.org/schema/p"
xmlns:c="http://www.springframework.org/schema/c"

idea能夠自動引入;

<bean id="student" class="com.abc.di03.Student" p:age="19" p:name="小明" p:school-ref="mySchool"/>
<bean id="student" class="com.abc.di04.Student" c:age="16" c:name="小紅" c:school-ref="mySchool"/>

4)數組與集合屬性注入

數組,集合中能夠存放基本的數據類型和對象類型;一樣:在map中,鍵和值能夠存放基本數據類型和對象。

在案例中數組已經定義存放String;

<bean id="some" class="com.abc.di05.Some">
    <!--數組賦值-->
    <property name="names">
        <array>
            <value>張三</value>
            <value>李四</value>
            <value>王五</value>
        </array>
    </property>
    <!--List-->
    <property name="myList">
        <list>
            <value>河南</value>
            <value>河北</value>
        </list>
    </property>
    <property name="schools">
        <list>
            <ref bean="aynu"/>
            <ref bean="tsinghua"/>
        </list>
    </property>
    <!--set集合賦值-->
    <property name="mySets">
        <set>
            <value>本科</value>
            <value>碩士</value>
            <value>博士</value>
        </set>
    </property>
    <!--map集合賦值-->
    <property name="myMap">
        <map>
            <entry key="mobile" value="123456"/>
            <entry key="QQ" value="654321"/>
        </map>
    </property>
    <!--properties集合-->
    <property name="myPros">
        <props>
            <prop key="email">123456@qq.com</prop>
            <prop key="address">文明大道</prop>
        </props>
    </property>
</bean>

能夠看到使用 標籤爲數組賦值;list中: ;set中: ;map中使用 關聯關係;在Properties中 標籤能夠寫多個 關聯;

要注意
list和set集合的區別,list中能夠容許重複元素的存在,在set中不容許重複元素存在;set十分接近「數學中集合」的概念--無序不可重複;

properties,map中的鍵也不能重複,重複的話對應的值就會覆蓋

向數組中賦值時能夠將值寫成下面的簡寫方式:

<property name="names" value="張三,李四">
    <!--<array>
        <value>張三</value>
        <value>李四</value>
        <value>王五</value>
    </array>-->
</property>

必須爲基本數據類型而且須要使用英文的逗號。

5)域屬性自動注入

域屬性:一個對象屬性

域屬性自動注入:能夠經過指定域屬性的類型注入或者經過指定域屬性名稱兩種方式注入;

student類的屬性:

private String name;
private int age;
//域屬性
private School school;//也須要有setter方法

配置文件:

<!--
    byType:同種類型的對象(包括子類的對象)只能有一個
    byName:注入的bean的id和域屬性的屬性名相同
-->
<bean id="student" class="com.abc.di06.Student" autowire="byName">
    <property name="age" value="20"/>
    <property name="name" value="張三"/>
</bean>
<bean id="school" class="com.abc.di06.MiddleSchool">
    <property name="sname" value="一中"/>
    <property name="address" value="文明大道"/>
</bean>

autowire="byName"

經過指定域屬性的id進行自動注入,要求域屬性名要和如上id="school"的id值相等;

若是使用autowire="byType"經過域屬性的類型注入,那麼同種類型的對象只能有一個,只要知足"is -a"關係,即:包括同種子類對象和它自身也不行;

6)SPEL注入

主要使用#{},可調用屬性,方法。

<!--首先定義一個類,注入屬性,T調用Math類-->
<bean id="person" class="com.abc.di07.Person">
    <property name="pname" value="張三"/>
    <property name="page" value="#{T(java.lang.Math).random()*100}"/>
</bean>
<!--能夠將person中的值注入到student中-->
<bean id="student" class="com.abc.di07.Student">
    <property name="name" value="#{person.pname}"/>
    <!--<property name="age" value="#{person.page>30?30:person.page}"/>-->
    <property name="age" value="#{person.computeAge()}"/>
</bean>

實例:將一個對象中的值注入另外一個對象中

若是須要簡單判斷,可使用三模運算符(註釋);若是複雜運算能夠在調用的對象中寫一個方法並調用;

註解簡單實現

首先在主配置文件中配置註解掃描:

<!--註冊組件掃描器-->
<context:component-scan base-package="com.abc.di01"/>
  1. 設值注入

@Component()註解,聲明組件至關於在註解中定義一個bean;

@Value()註解,用於設置注入至關於bean裏面的property,給這個bean添加屬性;須要有屬性的setter();

//在註解中若是隻有"value"一個參數,能夠將value省略,只留下value的值;
@Component("mySchool")
public class School {
    @Value("一中")
    private String sname;

    public void setSname(String sname) {
        this.sname = sname;
    }
}
  1. 域屬性自動注入

    @Autowired:經過類型自動注入;

    @Qualifier()經過域對象的名稱進行注入

@Component(value = "student")
public class Student {
    @Value("小劉")
    private String name;
    @Value("18")
    private int age;
    //byType方式自動注入
    //@Autowired
    //byName方式自動注入
    //@Qualifier("mySchool")
    private School school;

    public void setName(String name) {
        this.name = name;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public void setSchool(School school) {
        this.school = school;
    }
}
相關文章
相關標籤/搜索