Spring4(3)——IOC控制反轉
阿新 • • 發佈:2018-11-07
1.Spring裝配一個bean
在前一章中已涉及到此知識點,通俗的來講:在建立People實體之後,在beans.xml 中配置,然後在實現類中呼叫 beans.xml檔案,即裝配完成,呼叫預設的構造方法。
-
建立實體 (People.java) 類
public class People { private int id; private String name; private int age; // 構造方法 public People() { super(); }
-
配置beans.xml 檔案
<bean id="people" class="com.java1234.entity.People"></bean>
-
呼叫beans.xml 檔案
ApplicationContext ac=new
2.依賴注入
- 1. 屬性注入;
- 2. 建構函式注入;(通過型別;通過索引;聯合使用)
- 3. 工廠方法注入;(非靜態工廠,靜態工廠)
- 4. 泛型依賴注入;(參考後面 Spring4 整合 Hibernate4 記錄)
<!-- 裝配 --> <bean id="people" class="com.java1234.entity.People"></bean> <!--
<!-- 建構函式注入(通過型別)--> <bean id="people3" class="com.java1234.entity.People"> <constructor-arg type="int" value="2"></constructor-arg> <constructor-arg type="String" value="李四"></constructor-arg> <constructor-arg type="int" value="22"></constructor-arg> </bean> <!-- 建構函式注入(通過索引)--> <bean id="people4" class="com.java1234.entity.People"> <constructor-arg index="0" value="3"></constructor-arg> <constructor-arg index="1" value="王五"></constructor-arg> <constructor-arg index="2" value="55"></constructor-arg> </bean> <!-- 建構函式注入(型別索引聯合使用)--> <bean id="people5" class="com.java1234.entity.People"> <constructor-arg index="0" type="int" value="4"></constructor-arg> <constructor-arg index="1" type="String" value="招六"></constructor-arg> <constructor-arg index="2" type="int" value="66"></constructor-arg> </bean>
<!-- 工廠方法注入(非靜態工廠)--> <bean id="peopleFactory" class="com.java1234.factory.PeopleFactory"></bean> <bean id="people6" factory-bean="peopleFactory" factory-method="createPeople"></bean> <!-- 工廠方法注入(靜態工廠)--> <bean id="people7" class="com.java1234.factory.PeopleFactory2" factory-method="createPeople"></bean>public class Test2 { public static void main(String[] args) { ApplicationContext ac=new ClassPathXmlApplicationContext("beans.xml"); People people=(People)ac.getBean("people"); System.out.println(people); // 屬性注入 People people2=(People)ac.getBean("people2"); System.out.println(people2); // 構造方法注入 People people3=(People)ac.getBean("people3"); System.out.println(people3); People people4=(People)ac.getBean("people4"); System.out.println(people4); People people5=(People)ac.getBean("people5"); System.out.println(people5); // 工廠方法注入 People people6=(People)ac.getBean("people6"); System.out.println(people6); People people7=(People)ac.getBean("people7"); System.out.println(people7); } }
3.注入引數
-
1. 基本型別值:參見上一節屬性注入
-
2. 注入 bean;
<!-- 在 people2 裡面注入 dog1 --> <bean id="dog1" class="com.java1234.entity.Dog"> <property name="name" value="Jack"></property> </bean> <bean id="people2" class="com.java1234.entity.People"> <property name="id" value="1"></property> <property name="name" value="張三"></property> <property name="age" value="11"></property> <property name="dog" ref="dog1"></property> <!-- bean 注入 ,在 People.java 類中宣告 dog類--> </bean>
-
3. 內部 bean;
<bean id="people3" class="com.java1234.entity.People"> <property name="id" value="1"></property> <property name="name" value="張三"></property> <property name="age" value="11"></property> <property name="dog"> <bean class="com.java1234.entity.Dog"> <property name="name" value="Tom"></property> </bean> </property> </bean>
-
4. null 值;
<bean id="people4" class="com.java1234.entity.People"> <property name="id" value="1"></property> <property name="name" value="張三"></property> <property name="age" value="11"></property> <property name="dog"> <null></null> </property> </bean>
-
5. 級聯屬性;
<bean id="people5" class="com.java1234.entity.People"> <property name="id" value="1"></property> <property name="name" value="張三"></property> <property name="age" value="11"></property> <property name="dog.name" value="Jack2"></property>
<!-- 因為此處用到了dog的屬性,需要在宣告的時候new一個dog物件。( private Dog dog = new Dog(); ) --> </bean> -
6. 集合型別屬性;
<bean id="people6" class="com.java1234.entity.People"> <property name="id" value="1"></property> <property name="name" value="張三"></property> <property name="age" value="11"></property> <property name="dog" ref="dog1"></property> <property name="hobbies"> <list> <!-- list集合,可重複 --> <value>唱歌</value> <value>跳舞</value> </list> </property> <property name="loves"> <set> ·<!-- set集合,不可重複 --> <value>唱歌2</value> <value>跳舞2</value> </set> </property> <property name="works"> <map> <!-- Map鍵值對 --> <entry> <key><value>上午</value></key> <value>寫程式碼</value> </entry> <entry> <key><value>下午</value></key> <value>測試程式碼</value> </entry> </map> </property> <property name="addresses"> <props> <!-- props 輸入結果和Map類似,props 主要用於一些系統的配置--> <prop key="address1">aaaaa</prop> <prop key="address2">bbbbb</prop> </props> </property> </bean>
private Dog dog; private List<String> hobbies=new ArrayList<String>(); private Set<String> loves=new HashSet<String>(); private Map<String,String> works=new HashMap<String,String>(); private Properties addresses=new Properties();
4.自動裝配
通過配置 default-autowire 屬性(byName,byType,constructor),Spring IOC 容器可以自動為程式注入 bean;預設是 no,不啟用自動裝配;
<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" default-autowire="constructor"> <!-- 在此處設定 -->
- byName:通過名稱進行自動匹配,根據類中宣告的屬性名稱選擇注入的值;
// People.java private Dog dog1;
<!-- beans.xml --> <bean id="dog1" class="com.java1234.entity.Dog"> <property name="name" value="Tom"></property> </bean> <bean id="dog2" class="com.java1234.entity.Dog"> <property name="name" value="Jack"></property> </bean> <bean id="people1" class="com.java1234.entity.People"> <property name="id" value="1"></property> <property name="name" value="張三"></property> <property name="age" value="11"></property> </bean>
// 測試 public void test1() { private ApplicationContext ac=new ClassPathXmlApplicationContext("beans.xml"); People people=(People)ac.getBean("people1"); System.out.println(people); }
結果是:取出的狗名叫:Tom, 注意看People.java裡面宣告的狗是 dog1.
.
- byType:根據型別進行自動匹配,class="com.java1234.entity.Dog ;
- constructor:和 byType 類似,只不過它是根據構造方法注入而言的,根據型別,自動注入;
建議:自動裝配機制慎用,它遮蔽了裝配細節,容易產生潛在的錯誤;
5.方法注入
Spring bean 作用域預設是 單例 singleton; 可以通過配置 prototype ,實現多例; 方法注入 lookup-method .
- 預設單例 :每次獲取的例項都是一樣的
System.out.println(ac.getBean("dog")=ac.getBean("dog")); //返回true
- 配置多例:每次獲取的例項是不一樣的 ( scope="prototype" )
<bean id="dog" class="com.java1234.entity.Dog" scope="prototype"> <property name="name" value="Jack"></property> </bean>
System.out.println(ac.getBean("dog")=ac.getBean("dog")); //返回false
注:當把dog bean作為屬性注入給其他bean是,是同一條狗,而不是新的!所以可以使用lookup-method 方法注入修改
- bean注入時lookup-method
<bean id="dog" class="com.java1234.entity.Dog" scope="prototype"> <property name="name" value="Jack"></property> </bean> <bean id="people1" class="com.java1234.entity.People"> <property name="id" value="1"></property> <property name="name" value="張三"></property> <property name="age" value="11"></property> <lookup-method name="getDog" bean="dog"/> <!-- lookup-method --> </bean>
注:此時要將getDog的方法改成抽象方法
public abstract class People { private Dog dog; public abstract Dog getDog(); public void setDog(Dog dog) { this.dog = dog; } }
6.方法替換
假如,people1 有一條叫 Tom 的狗,people2 有一條叫 Jack 的狗,現在 people1 想要名叫 Jack 即 people2 的狗,即可用方法替換來實現。
此時需要將 people2 的 getDog() 方法替換成people1 的。
- people2 實現介面 MethodReplacer
public class People2 implements MethodReplacer { @Override public Object reimplement(Object arg0, Method arg1, Object[] arg2) throws Throwable { Dog dog=new Dog(); dog.setName("Tom"); return dog; } }
<bean id="people2" class="com.java1234.entity.People2"></bean> <bean id="people1" class="com.java1234.entity.People"> <property name="id" value="1"></property> <property name="name" value="張三"></property> <property name="age" value="11"></property> <replaced-method name="getDog" replacer="people2"></replaced-method> <!-- 用people2裡面的reimplement來替換people1裡面的getDog方法 --> </bean>
7.Bean之間的關係
- 1. 繼承:抽象的Bean可以定義一些公共的屬性和方法( abstract="true" )
<!-- bstract="true" --> <bean id="abstractPeople" class="com.java1234.entity.People" abstract="true"> <property name="className" value="高三5班"></property> <property name="age" value="19"></property> </bean> <!-- parent="abstractPeople" --> <bean id="lisi" parent="abstractPeople"> <!-- 無需class,可不建立實體類 --> <property name="id" value="2"></property> <property name="name" value="李四"></property> <property name="age" value="20"></property> <!-- 屬性可重寫 --> </bean> <!-- 結果是:id=2——李四——高三5班——20歲 -->
- 2. 依賴:未加入依賴的時候,按順序執行bean;加入依賴後,會先去執行依賴的 bean ( depends-on="autority" ),可用於許可權設定
<!-- depends-on="autority" --> <bean id="zhangsan" parent="abstractPeople" depends-on="autority"> <property name="id" value="1"></property> <property name="name" value="張三"></property> </bean> <bean id="autority" class="com.java1234.service.Authority"></bean>
- 3. 引用:引用bean (ref),可參照前面的內容
8.Bean的作用範圍
- 1. singleton:Spring ioc 容器中僅有一個 Bean 例項,Bean 以單例的方式存在;
- 2. prototype:每次從容器中呼叫 Bean 時,都返回一個新的例項;
- 3. request: 每次 HTTP 請求都會建立一個新的 Bean;
- 4. session: 同一個 HTTP Session 共享一個 Bean;
- 5. global session: 同一個全域性 Session 共享一個 Bean,一般用於 Portlet 應用環境;
- 6. application: 同一個 Application 共享一個 Bean;
<!-- scope="singleton/prototype/....." --> <bean id="dog" class="com.java1234.entity.Dog" scope="singleton"> <property name="name" value="jack"></property> </bean>