1、IoC容器概述
IoC 全稱為 Inversion of Control
,翻譯為 “控制反轉”,它還有一個別名為 DI(Dependency Injection
),即依賴注入。
所謂 IOC ,就是由 Spring IOC 容器來負責對象的生命周期和對象之間的關系
該org.springframework.context.ApplicationContext
接口代表Spring IoC容器,並負責實例化,配置和組裝Bean。
容器通過讀取配置元數據來獲取有關要實例化,配置和組裝哪些對象的指令。
配置元數據以 XML ,Java批注 或 Java代碼 表示。
它使您能夠表達組成應用程序的對象以及這些對象之間的豐富相互依賴關系。
2、如何理解“控制反轉”呢
理解好它的關鍵在於我們需要回答如下四個問題:
- 誰控制誰:在傳統的開發模式下,我們都是采用直接 new 一個對象的方式來創建對象,也就是說你依賴的對象直接由你自己控制,但是有了 IOC 容器后,則直接由 IoC 容器來控制。所以“誰控制誰”,當然是 IoC 容器控制對象。
- 控制什么:控制對象。
- 為何是反轉:沒有 IoC 的時候我們都是在自己對象中主動去創建被依賴的對象,這是正轉。但是有了 IoC 后,所依賴的對象直接由 IoC 容器創建后注入到被注入的對象中,依賴的對象由原來的主動獲取變成被動接受,所以是反轉。
- 哪些方面反轉了:所依賴對象的獲取被反轉了。
3、bean總覽
3.1 命名方式
一共有三種,可以通過id、name還有外部通過<alias name="bean" alias="aliasName">標簽命名。
每個bean具有一個或多個標識符。這些標識符在承載Bean的容器內必須唯一。一個bean通常只有一個標識符。
3.2 實例化方式
構造方法實例化;
<!--構造方法實例化--> <bean id="teacher" class="com.doubleh.pojo.Teacher"> <constructor-arg name="id" value="1"></constructor-arg> <constructor-arg name="name" value="李白"></constructor-arg> </bean>
靜態工廠方法實例化;
<!--靜態工廠方法實例化:構造方法私有化用,例如單例類--> <!-- public class Teacher{ private static Teacher teacher = new Teacher(); private Teacher() { } public static Teacher createInstance() { return teacher; } } --> <bean id="teacher" class="com.doubleh.pojo.Teacher" factory-method="createInstance"> </bean>
實例工廠方法實例化(暫未發現用處);
<!--實例工廠方法實例化--> <!-- public class DefaultServiceLocator { private static Teacher teacher = new Teacher(); private Teacher() { } public Teacher createInstance() { return teacher; } } --> <bean id="dsl" class="com.doubleh.pojo.DefaultServiceLocator"> </bean> <bean id="createInstance" factory-bean="dsl" factory-method="createInstance"></bean>
4、bean依賴注入方式
4.1 構造器注入
顧名思義就是被注入的對象通過在其構造方法中聲明依賴對象的參數列表,讓外部知道它需要哪些依賴對象。
//老師類 public class Teacher { private int id; private String name; public Teacher(int id, String name) { this.id = id; this.name = name; } @Override public String toString() { return "Teacher{" + "id=" + id + ", name='" + name + '\'' + '}'; } } //學生類 public class Student { private int id; private String name; private Teacher teacher; public Student(int id, String name, Teacher teacher) { this.id = id; this.name = name; this.teacher = teacher; } @Override public String toString() { return "Student{" + "id=" + id + ", name='" + name + '\'' + ", teacher=" + teacher + '}'; } }
<!--配置Teacher類--> <bean id="teacher" class="com.doubleh.pojo.Teacher"> <constructor-arg index="0" value="1"></constructor-arg> <constructor-arg index="1" value="屈原"></constructor-arg> </bean> <!--配置學生類--> <bean class="com.doubleh.pojo.Student" id="student" > <!--構造方法注入:根據參數下標賦值--> <constructor-arg index="0" value="1"></constructor-arg> <!--根據參數名賦值:推薦--> <constructor-arg name="name" value="李白"></constructor-arg> <!--根據數據類型賦值--> <constructor-arg type="com.doubleh.pojo.Teacher" ref="teacher"></constructor-arg> </bean>
構造方法通過<constructor-arg>標簽來注入,分別可以通過以下三種方式注入值:
參數下標(index)注入;
參數名(name)注入,推薦這種;
參數類型(name)注入;
4.2 setter注入
對於 JavaBean 對象而言,我們一般都是通過 getter 和 setter 方法來訪問和設置對象的屬性。所以,當前對象只需要為其所依賴的對象提供相對應的 setter 方法,就可以通過該方法將相應的依賴對象設置到被注入對象中。這種也比較靈活。
setter注入前提是JavaBean對象必須由setter方法,否則會報:
org.springframework.beans.NotWritablePropertyException:
Invalid property 'id' of bean class [com.doubleh.pojo.Student]:
Bean property 'id' is not writable or has an invalid setter method.
Does the parameter type of the setter match the return type of the getter?
setter注入通過<property>標簽來注入值;
<bean class="com.doubleh.pojo.Student" id="student" > <property name="id" value="1"></property> <property name="name" value="李白"></property> <property name="teacher" ref="teacher"></property> </bean>
各種類型值注入方式:
<bean class="com.doubleh.pojo.Student" id="student" > <!--基礎類型--> <property name="id" value="1"> </property> <!--bean引用類型--> <property name="teacher" ref="teacher"></property> <!--數組類型--> <property name="strs" > <array> <value>李白</value> <value>杜甫</value> <value>白居易</value> </array> </property> <!--List類型--> <property name="list"> <list> <ref bean="teacher"></ref> </list> </property> <!--Map類型--> <property name="map"> <map> <entry value="你好" key="a"></entry> <entry key="b" value="發順豐"></entry> <!--key-ref="" --> <entry key="c" value="{id = 3,name = 設計費}"> </entry> </map> </property> <!--Set類型--> <property name="set"> <set> <value>槍</value> <value>劍</value> </set> </property> <!--Properties類型--> <property name="props"> <props> <prop key="driver">com.mysql.com</prop> <prop key="url">jdbc:mysql://localhost</prop> </props> </property> <!--NULL類型--> <property name="t2"> <null /> </property> </bean>
4.3 p-namespace允許您使用bean
元素的屬性(而不是嵌套 <property/>
元素)來描述協作bean的屬性值,或同時使用這兩者。
<beans></beans>標簽中添加配置
xmlns:p="http://www.springframework.org/schema/p"
<!--普通模式--> <!-- <bean id="people" class="com.doubleh.pojo.People"> <property name="name" value="李白"></property> </bean>--> <!--P-namespace注入模式--> <bean id="people" class="com.doubleh.pojo.People" p:name="杜甫"> </bean>
4.4 與具有p-namespace的XML Shortcut相似,在Spring 3.1中引入的c-namespace允許使用內聯屬性來配置構造函數參數,而不是嵌套constructor-arg
元素。
<beans></beans>標簽中添加配置
xmlns:c="http://www.springframework.org/schema/c"