Spring學習3:Spring依賴注入機制

Spring依賴注入:

  • Spring 基於構造函數的依賴注入
  • Spring 基於設值函數的依賴注入
  • Spring 注入內部Beans
  • Spring 注入集合

一、Spring基於構造函數的依賴注入:

當容器調用帶有一組參數的類構造函數時,基於構造函數的id就可以完成,其中每個參數代表一個對其他類的依賴,我們用一個例子來理解Spring基於構造函數的依賴注入:

步驟 描述
1 創建一個名爲 SpringExample 的項目,並在創建的項目中的 src 文件夾下創建包 com.tutorialspoint 。
2 使用 Add External JARs 選項添加必需的 Spring 庫
3 在 com.tutorialspoint 包下創建 Java類 TextEditor,SpellChecker 和 MainApp
4 在 src 文件夾下創建 Beans 的配置文件 spring-conf.xml
5 最後一步是創建所有 Java 文件和 Bean 配置文件的內容並按照如下所示的方法運行應用程序。

TextEditor.java文件的內容:

package studio_day_2;

public class TextEditor {
    private SpellChecker spellChecker;
    public TextEditor(SpellChecker spellChecker){
        System.out.println("Inside TextEditor constructor." );
        this.spellChecker=spellChecker;
    }
    public void spellCheck() {
        spellChecker.checkSpelling();
    }
}

SpellChecker.java文件內容:

package studio_day_2;

public class SpellChecker {
    public SpellChecker(){
        System.out.println("Inside SpellChecker constructor." );
    }
    public void checkSpelling() {
        System.out.println("Inside checkSpelling." );
    }
}

Main文件內容:

package studio_day_2;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Main {
    public static void main(String[] args) {
        ApplicationContext context=new ClassPathXmlApplicationContext("spring-conf.xml");
        TextEditor re = (TextEditor) context.getBean("texteditor");
        re.spellCheck();
    }
}

spring-conf.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.xsd">


    <bean id="texteditor" class="studio_day_2.TextEditor">
        <constructor-arg ref="spellChecker" />
    </bean>

    <bean id="spellChecker" class="studio_day_2.SpellChecker"/>

</beans>

配置正常的情況,運行Main主函數:
在這裏插入圖片描述
其他情況:

  1. 當如果存在不止一個參數的時候,我們把參數傳遞給構造函數的時候,可能會存在歧義,所以我們在bean配置定義的時候,參數的順序與構造函數的順序相一致就可以了。
    比如:
package x.y;
public class Foo {
   public Foo(Bar bar, Baz baz) {
      // ...
   }
}

spring-conf.xml配置文件

<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>
  1. 還有一種情況就是,多個參數,並且每種參數的類型不相同,我們只需要用不同的類型傳遞即可,添加bean定義中的type屬性:
package x.y;
public class Foo {
   public Foo(int year, String name) {
      // ...
   }
}

spring-conf.xml文件

<beans>

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

</beans>
  1. 最簡單的傳遞方式,還是使用index屬性來顯式的指定構造函數的索引:
<beans>

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

</beans>

使用index的順序給構造參數進行賦值即可。

二、Spring基於設值函數的依賴注入:

當容器用一個無參的構造函數或者一個無參的靜態factory方法來初始化你的bean後,通過容器在你的bean上調用設值函數,基於設值函數的DI就可以完成。
下面給出一個例子,來理解Spring基於設值函數的依賴注入

步驟 描述
1 創建一個名爲 SpringExample 的項目,並在創建的項目中的 src 文件夾下創建包 com.tutorialspoint 。
2 使用 Add External JARs 選項添加必需的 Spring 庫
3 在 com.tutorialspoint 包下創建 Java類 TextEditor,SpellChecker 和 MainApp
4 在 src 文件夾下創建 Beans 的配置文件 spring-conf.xml
5 最後一步是創建所有 Java 文件和 Bean 配置文件的內容並按照如下所示的方法運行應用程序。

以下是TextEditor.java文件內容:

package studio_day_2;

public class TextEditor {
    private SpellChecker spellChecker;
    // a setter method to inject the dependency.
    public void setSpellChecker(SpellChecker spellChecker) {
        System.out.println("Inside setSpellChecker." );
        this.spellChecker = spellChecker;
    }
    // a getter method to return spellChecker
    public SpellChecker getSpellChecker() {
        return spellChecker;
    }
    public void spellCheck() {
        spellChecker.checkSpelling();
    }
}

以下是SpellChecker.java文件內容:

package studio_day_2;

public class SpellChecker {
    public SpellChecker(){
        System.out.println("Inside SpellChecker constructor." );
    }
    public void checkSpelling() {
        System.out.println("Inside checkSpelling." );
    }
}

以下是spring-conf.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.xsd">


    <bean id="texteditor" class="studio_day_2.TextEditor">
        <property name="spellChecker" ref="spellChecker"/>
    </bean>

    <bean id="spellChecker" class="studio_day_2.SpellChecker"/>


</beans>

基於設值函數的依賴注入構造函數的依賴注入唯一的區別在於bean定義的不同,定義屬性 的ref等於bean對應的id類就成爲了設值函數的依賴注入,但是在TextEditor.java中我們必須定義POJO的類似set和get函數。自己的理解就是在bean定義中,定義我們在創建對象的時候,我們所需要的賦值操作,我們可以使用bean的依賴注入機制,對容器new的新對象進行賦值操作,比如這個例子中texteditor這個bean,就使用了spellChecker的值。
運行結果:
在這裏插入圖片描述

三、Spring注入內部bean

Spring注入內部bean實質就是在一個bean中再去定義一個內部的bean,這個bean歸該bean所有的定義方式就是Spring的內部注入方式,其他代碼和上一節基於設值函數的依賴注入完全相同。
如下所示:

<?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 id="outerBean" class="...">
      <property name="target">
         <bean id="innerBean" class="..."/>
      </property>
   </bean>

</beans>

把以下這spring-conf.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.xsd">


    <bean id="texteditor" class="studio_day_2.TextEditor">

        <property name="spellChecker">
            <bean id="spellChecker" class="studio_day_2.SpellChecker"/>
        </property>

    </bean>

</beans>

運行結果如下:
在這裏插入圖片描述

四、Spring注入集合

我們從前面的學習可以學到如何使用value屬性來配置基本數據類型和在你的bean配置文件中使用標籤的ref屬性來配置對象引用。這兩種情況下處理奇異值傳遞給一個bean。
但是如果我們現在想要傳遞多個值,那怎麼辦呢?
我們可以使用Java Collection類型:List、Set、Map和Properties來傳遞多個值:

元素 描述
list 它有助於連線,如注入一列值,允許重複。
set 它有助於連線一組值,但不能重複。
map 它可以用來注入名稱-值對的集合,其中名稱和值可以是任何類型。
props 它可以用來注入名稱-值對的集合,其中名稱和值都是字符串類型。

你可以使用list或者set來連接任何java.util.Collection的實現或數組。
你可能會遇到兩種情況:

  • 1. 傳遞集合中直接的值
  • 2. 傳遞一個bean的引用作爲集合的元素

我們用一個例子來理解這個集合注入機制:

步驟 描述
1 創建一個Spring的項目
2 使用 Add External JARs 選項,添加所需的 Spring 庫
3 創建類JavaCollection、Main類
4 在 src 文件夾中創建 Beans 配置文件 spring-conf.xml
5 最後一步是創建的所有Java文件和Bean配置文件的內容,並運行應用程序,解釋如下所示。

這是javaCollection.java文件的內容:

package studio_day_2;
import java.util.*;

public class JavaCollection {
    List addressList;
    Set  addressSet;
    Map  addressMap;
    Properties addressProp;
    // a setter method to set List
    public void setAddressList(List addressList) {
        this.addressList = addressList;
    }
    // prints and returns all the elements of the list.
    public List getAddressList() {
        System.out.println("List Elements :"  + addressList);
        return addressList;
    }
    // a setter method to set Set
    public void setAddressSet(Set addressSet) {
        this.addressSet = addressSet;
    }
    // prints and returns all the elements of the Set.
    public Set getAddressSet() {
        System.out.println("Set Elements :"  + addressSet);
        return addressSet;
    }
    // a setter method to set Map
    public void setAddressMap(Map addressMap) {
        this.addressMap = addressMap;
    }
    // prints and returns all the elements of the Map.
    public Map getAddressMap() {
        System.out.println("Map Elements :"  + addressMap);
        return addressMap;
    }
    // a setter method to set Property
    public void setAddressProp(Properties addressProp) {
        this.addressProp = addressProp;
    }
    // prints and returns all the elements of the Property.
    public Properties getAddressProp() {
        System.out.println("Property Elements :"  + addressProp);
        return addressProp;
    }
}

下面是Main.java文件的內容:

package studio_day_2;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Main {
    public static void main(String[] args) {
        ApplicationContext context=new ClassPathXmlApplicationContext("spring-conf.xml");
        JavaCollection javaCollection=(JavaCollection) context.getBean("javaCollection");
        javaCollection.getAddressList();
        javaCollection.getAddressMap();
        javaCollection.getAddressProp();
        javaCollection.getAddressSet();
    }
}

下面是spring-conf.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.xsd">


    <bean id="javaCollection" class="studio_day_2.JavaCollection">
        <!-- results in a setAddressList(java.util.List) call -->
        <property name="addressList">
            <list>
                <value>INDIA</value>
                <value>Pakistan</value>
                <value>USA</value>
                <value>USA</value>
            </list>
        </property>

        <!-- results in a setAddressSet(java.util.Set) call -->
        <property name="addressSet">
            <set>
                <value>INDIA</value>
                <value>Pakistan</value>
                <value>USA</value>
                <value>USA</value>
            </set>
        </property>

        <!-- results in a setAddressMap(java.util.Map) call -->
        <property name="addressMap">
            <map>
                <entry key="1" value="INDIA"/>
                <entry key="2" value="Pakistan"/>
                <entry key="3" value="USA"/>
                <entry key="4" value="USA"/>
            </map>
        </property>

        <!-- results in a setAddressProp(java.util.Properties) call -->
        <property name="addressProp">
            <props>
                <prop key="one">INDIA</prop>
                <prop key="two">Pakistan</prop>
                <prop key="three">USA</prop>
                <prop key="four">USA</prop>
            </props>
        </property>
    </bean>
</beans>

一切正常的情況下,運行結果如下:
在這裏插入圖片描述

注入Bean引用:

<?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 Definition to handle references and values -->
   <bean id="..." class="...">

      <!-- Passing bean reference  for java.util.List -->
      <property name="addressList">
         <list>
            <ref bean="address1"/>
            <ref bean="address2"/>
            <value>Pakistan</value>
         </list>
      </property>

      <!-- Passing bean reference  for java.util.Set -->
      <property name="addressSet">
         <set>
            <ref bean="address1"/>
            <ref bean="address2"/>
            <value>Pakistan</value>
         </set>
      </property>

      <!-- Passing bean reference  for java.util.Map -->
      <property name="addressMap">
         <map>
            <entry key="one" value="INDIA"/>
            <entry key ="two" value-ref="address1"/>
            <entry key ="three" value-ref="address2"/>
         </map>
      </property>

   </bean>

</beans>

在使用 以上的bean定義的時候,我們必須定義setter方法。

注入null和空字符串的值

<bean id="..." class="exampleBean">
   <property name="email" value=""/>
</bean>

這個代碼相當於java代碼中的:exampleBean.setEmail("")
如果你需要傳遞一個NULL值:

<bean id="..." class="exampleBean">
   <property name="email"><null/></property>
</bean>

前面的例子相當於 Java 代碼:exampleBean.setEmail(null)

總的來說spring的依賴注入機制是爲了能更加靈活的管理Bean之間的依賴關係。

發佈了44 篇原創文章 · 獲贊 26 · 訪問量 4351
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章