Spring依賴注入---

菜雞03號發表於2016-11-05
學習Spring,時間一長就把最開始學的基礎生疏掉了...算是寫個筆記以便以後複習吧
 
什麼bean,在Spring裡可以理解為元件。可以聯絡一下我在前一篇筆記《理解Spring框架的控制反轉——學習筆記》中放進IoC容器裡的東西,比如說放在容器例項化的類,在容器中依賴注入的類...等等。可以先配置一個簡單的bean看看,程式碼如下:
 
首先是一個建立一個Bean類,其實也就是個普通的類,為其中屬性提供了setter而已:
 
複製程式碼
public class Fruit{
  private String color;
  private String name;
 
  public Fruit(){}
  public Fruit(String name,String color){
      this.color=color;
      this.name=name;          
  }        
  public void setColor(String color) {
    this.color = color;
  }
  public void setName(String name) {
    this.name = name;
  }
 public void mySaid(){
  System.out.println("我是"+name+",我的顏色是:"+color);  
  }
}
複製程式碼
 配置檔案就索性名為bean.xml,放在classpath下,以便待會例項化容器的時候找到它,程式碼如下:
 
複製程式碼
<?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-2.5.xsd">
    <bean id="fruit" class="com.czh.Fruit">
     <!--下面是setter注入-->
        <property name="color" value="red"/>
        <property name="name">        
            <value>apple</value>
        </property>
    <!--下面是構造器注入-->  
    <constructor-arg>
      <value>red</value>
       </constructor-arg>
       <constructor-arg>
          <value>red</value>
       </constructor-arg>
    </bean>
</beans>
複製程式碼
這樣一來,bean就配置好了。上面程式碼裡setter注入用了兩種寫法,效果是相同的,都會將value值注入到相應的屬性中。
 
而且要注意的是,<property>標籤是指要注入的屬性,它是通過name的值來找到相應屬性的。正如上面程式碼所示,<property name="color" value="red"/>,那麼它就會去找這個bean所設定的類裡(上面程式碼裡,類為”com.czh.Fruit")的一個名為setColor的方法,然後注入value值。同理,如果property的name為“abc",則容器也會到類裡找setAbc方法。
 
元件寫好了,也配置進了容器中,下一步就是例項化容器:
 
複製程式碼
public class Main{
    public static void main(String[] args) {
        ApplicationContext context=new ClassPathXmlApplicationContext("bean.xml");//例項化容器
        Fruit fruit=context.getBean("fruit");//找到配置好的bean
        fruit.mySaid();            
    }
}    
複製程式碼
容器例項化的方法還有很多種,用ClassPathXmlApplicationContext類可以從classpath路徑上例項化容器。例項化容器之後,就可以用getBean方法去找配置在容器中的元件了,比如context.getBean("fruit");這個時候容器就把該注入的內容注入進元件,並例項化該元件,於是這時候呼叫該元件的mySaid()方法,可以看到輸出"我是apple,我的顏色是:red".
 
 
 
上面介紹了最簡單的配置,和例項化容器。現在來看看如何在Bean配置檔案指定對Bean的引用..這句話可以理解成這樣:A類中需要引用B類的方法,首先需要在A類中例項化B類,然後使用B類方法。但是在使用容器的情況下,可以通過Setter或者構造器把B類注入到A類中...這就是一個Bean對另一個Bean的引用了,具體看下面程式碼:
 
複製程式碼
public class Fruit{
  private String color;
  private String name;
  private Price price;     //Price類
 
  public Fruit(){}
  public Fruit(String name,String color,Price price){
      this.color=color;
      this.name=name;          
      this.price=price;  
  }        
  public void setColor(String color) {
    this.color = color;
  }
  public void setName(String name) {
    this.name = name;
  }
  public void setPrice(Price price){
    this.price=price;
  }
 public void mySaid(){
  System.out.println("我是"+name+",我的顏色是:"+color+",我的價格是:"+price.getPrice());  
  }
}    
複製程式碼
這裡需要用到Price類:
 
複製程式碼
public class Price{
 
  private String price;    
 
  public void setPrice(String price){
    this.price=price;
  }
 public String getPrice(){
    return price;
  }
}    
複製程式碼
於此同時,bean的配置應該改為:宣告另一個bean(即price),並注入到Fruit中
 
複製程式碼
<?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-2.5.xsd">
    <bean id="fruit" class="com.czh.Fruit">
     <!--下面是setter注入-->
        <property name="color" value="red"/>
        <property name="name">        
            <value>apple</value>
        </property>
        <property name="price">
            <ref bean="price"/><!-- 用ref的bean屬性可以引用其他XML的bean -->
            <ref local="price"/><!-- 用ref的bean屬性只能引用本XML的bean -->
        </property>
    <!--下面是構造器注入-->  
    <constructor-arg>
      <value>red</value>
       </constructor-arg>
       <constructor-arg>
          <value>red</value>
       </constructor-arg>
       <constructor-arg>
          <ref bean="price"/>
       </constructor-arg>
    </bean>
 
    <bean id="price" class="com.czh.Price">
        <property name="price" value="10"/>
    </bean>
</beans>    
複製程式碼
從上面的配置中,應該可以很清楚看到,要引用bean只需要在property下用<ref>標籤去獲得bean的id即可。
 
當然,也可以這麼寫:<property name="price" ref="price">
 
還有另一個引用bean的方式,那就是:內部bean。內部bean的意思就是說直接把<bean id="price" class="com.czh.price">...</bean>寫在Fruit Bean的property下。這樣說可能不是很明白,那就看看下面的程式碼吧:(內部bean的缺點是,放在的Fruit Bean裡面,則只有Fruit Bean可以引用它,其他的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-2.5.xsd">
    <bean id="fruit" class="com.czh.Fruit">
     <!--下面是setter注入-->
        ...
        <property name="price">
             <bean id="price" class="com.czh.Price">
                 <property name="price" value="10"/>
              </bean>
        </property>
    <!--下面是構造器注入-->  
   ...
       <constructor-arg>
              <bean id="price" class="com.czh.Price">
                <property name="price" value="10"/>
            </bean>
       </constructor-arg>
    </bean>
</beans>                
複製程式碼
 
 
 最基本的注入配置已經瞭解了。接下來應該考慮的兩個問題是:1、假如配置的時候忘記了注入怎麼辦,漏掉了幾個property導致輸出都是null卻很難從那麼多配置中一下找到寫少的部分。2、每一個Bean都要自己配置和注入,有沒有什麼辦法可以減少手工配置?
 
這兩個問題的解決就要看“基於註解的配置:@Required和@Autowired"...
 
首先來看看@Requried,順便理解一下註解在框架中起的作用
 
檢查屬性是否注入是上面所說要考慮的兩個問題之一。在spring中可以使用依賴檢查的特性來解決這個問題,依賴檢查很簡單,只需要在bean裡新增一個dependency-check屬性就可以了,具體的看看下面程式碼:
 
複製程式碼
<?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-2.5.xsd">
    <bean id="fruit" class="com.czh.Fruit" dependency-check="all">
     <!--下面是setter注入-->
        ...
        <property name="price">
             <bean id="price" class="com.czh.Price">
                 <property name="price" value="10"/>
              </bean>
        </property>
    <!--下面是構造器注入-->  
   ...
       <constructor-arg>
              <bean id="price" class="com.czh.Price">
                <property name="price" value="10"/>
            </bean>
       </constructor-arg>
    </bean>
</beans>  
複製程式碼
dependency-check="all"意味著對簡單型別的注入,和物件的注入(即bean的引用)都進行檢查。
dependency-check="simple"意味著對簡單型別(int,string...)的注入進行檢查。
dependency-check="object"意味著對 物件的注入(即bean的引用)進行檢查。它們一旦檢查未setter,就會丟擲UnsatisfiedDenpendencyException。
不過這個dependency-check好像在spring 3.0中使用會報錯,所以當基於註解的@Requried可以用於與它一樣的作用的時候,就使用@Requried註解吧。
Spring的一個Bean後置處理器(RequiredAnnotationBeanPostProcessor)可以檢查所有具有@Requried註解的屬性是否被設定,可以繼續上面水果類的例子看看這個@Requried如何放置,程式碼如下:
複製程式碼
public class Fruit{
  private String color;
  private String name;
  private Price price;     //Price類
 
  public Fruit(){}
  public Fruit(String name,String color,Price price){
      this.color=color;
      this.name=name;          
      this.price=price;  
  }
  @Requried         
  public void setColor(String color) {
    this.color = color;
  }
  @Requried 
  public void setName(String name) {
    this.name = name;
  }
  @Requried 
  public void setPrice(Price price){
    this.price=price;
  }
 public void mySaid(){
  System.out.println("我是"+name+",我的顏色是:"+color+",我的價格是:"+price.getPrice());  
  }
}   
複製程式碼
放置@Required註解很簡單,像上面程式碼那樣就可以了。Bean.xml那裡還得做點功夫,不過也很簡單,Spring 2.5以上的版本,我們只需要在xml中加上一句話就可以了,像這樣:<context:annotation-config/>,不過還是看看程式碼吧,在beans那塊加了些東西,否則會無法使用<context>標籤。程式碼如下:
 
複製程式碼
<?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:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans 

相關文章