Spring依賴注入---
學習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"