IOC控制反轉(IoC,Inversion of Control), 是一個概念,是一種思想。控制反轉就是對對象控制權的轉移,從程序代碼自己反轉到了外部容器。把對象的建立、初始化、 銷燬等工做交給spring容器來作。由spring容器控制對象的生命週期。 DI依賴注入:Dependency Injection。 依賴注入DI是指程序運行過程當中,若須要調用另外一個對象協助時,無須在代碼中建立被調用者,而是依賴於外部容器,由外部容器建立後傳遞給程序。依賴注入是目前最優秀的解耦方式。依賴注入讓Spring的Bean之間以配置文件的方式組織在一塊兒,而不是以硬編碼的方式耦合在一塊兒的。 IoC與DI的關係 IoC是一個概念,是一種思想,其實現方式多種多樣。當前比較流行的實現方式之一是DI。 IOC:控制反轉, 將 new 的過程交給spring容器去處理java
<?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">
</beans>
複製代碼
3.. 在Spring的配置文件中聲明User 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.xsd">
<!-- 在容器中註冊UserBean -->
<bean class="com.dpb.javabean.UserBean" id="userBean"></bean>
</beans>
複製代碼
所謂的聲明,就是將本身的信息告訴Spring容器,例如id和class,Spring容器根據class,經過反射(默認使用的是無參構造方法)就能夠建立一個名爲user1的User對象。數組
public static void main(String[] args) {
//初始化Spring容器,當Spring容器初始化時,會自動加載配置文件,而後根據配置文件中的內容初始化Bean
ApplicationContext ac =
new ClassPathXmlApplicationContext("application.xml");
}
複製代碼
5. 初識化Spring容器以後,能夠看到User已經被建立出來了。 注意:上面這種初始化方式,要求User必須有一個無參構造方法,若是沒有無參構造方法,會拋出以下異常:
6.經過調用容器中的getBean方法能夠獲取Spring容器中的對象
public static void main(String[] args) {
//初始化Spring容器,當Spring容器初始化時,會自動加載配置文件,而後根據配置文件中的內容初始化Bean
ApplicationContext ac =
new ClassPathXmlApplicationContext("application.xml");
// 去Spring容器中獲取一個UserBean對象
UserBean user = ac.getBean("userBean", UserBean.class);
System.out.println(user);
}
複製代碼
7. 也能夠經過類型直接獲取一個Bean的實例
public static void main(String[] args) {
//初始化Spring容器,當Spring容器初始化時,會自動加載配置文件,而後根據配置文件中的內容初始化Bean
ApplicationContext ac =
new ClassPathXmlApplicationContext("application.xml");
// 去Spring容器中獲取一個UserBean對象 經過類型直接獲取
UserBean user = ac.getBean( UserBean.class);
System.out.println(user);
}
複製代碼
這種方式有潛在的隱患:若是Spring容器中有多個User的實例,此時就會報錯 bash
實際開發過程當中咱們能夠忽略id和name的區別。能夠混合使用。經過getBean()方法均可以獲取,這個是個重載的方法。app
id="user1,user2,user3"
表示bean有一個名字,這個名字就是user1,user2,user3
name="user1,user2,user3"
表示bean有多個名字,多個名字分別是user一、user2以及user3
複製代碼
在同一配置文件中ID不要出現重複的。框架
/**
* ApplicationContext 方式加載
*/
@Test
public void test1() {
// 建立容器的同時 容器初始化,容器全部的bean建立完畢
ApplicationContext ac = new ClassPathXmlApplicationContext("application.xml");
// 去Spring容器中獲取一個UserBean對象 經過類型直接獲取
UserBean user = ac.getBean(UserBean.class);
System.out.println(user);
}
/**
* BeanFactory 方式加載
*/
@Test
public void test2() {
// 建立容器對象,BeanFactory當調用getBean獲取響應對象是才建立對象
BeanFactory bf = new XmlBeanFactory(new ClassPathResource("application.xml"));
// 去Spring容器中獲取一個UserBean對象 經過類型直接獲取
UserBean user = bf.getBean(UserBean.class);
System.out.println(user);
}
複製代碼
/**
* User 工廠類
* @author dpb[波波烤鴨]
*
*/
public class UserFactory {
/**
* 必須是static方法
* @return
*/
public static UserBean getInstance(){
return new UserBean();
}
}
複製代碼
application.xml文件中註冊ide
<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 class="com.dpb.factory.UserFactory" factory-method="getInstance" id="user2"/>
</beans>
複製代碼
獲取相應的實例 測試
在一些第三方框架使用過程 中,可能不得不使用靜態工廠注入或者實例工廠注入。ui
HttpUrlConnection
HttpClient
OkHttp
複製代碼
這裏以OkHttp爲例說明爲什麼須要靜態工廠注入 因爲OkHttpClient須要經過Builder進行建立,所以沒法直接使用構造方法注入。此時能夠經過靜態工廠注入。this
/**
* User 工廠類
* @author dpb[波波烤鴨]
*
*/
public class UserFactory {
/**
* 動態工廠方式獲取
* 普通方法
* @return
*/
public UserBean getInstance(){
return new UserBean();
}
}
複製代碼
<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 -->
<bean class="com.dpb.factory.UserFactory" id="userFactory"/>
<!-- 從工廠中獲取UserBean對象 -->
<bean id="user" factory-bean="userFactory" factory-method="getInstance"/>
</beans>
複製代碼
屬性注入主要是指如何給對象中的屬性賦值
<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">
<!-- 註冊UserBean -->
<bean class="com.dpb.javabean.UserBean" id="userBean">
<!-- 經過構造注入設置 -->
<constructor-arg name="id" value="1"/>
<constructor-arg name="name" value="波波烤鴨"/>
<constructor-arg name="age" value="18"/>
</bean>
</beans>
複製代碼
<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">
<!-- 註冊UserBean -->
<bean class="com.dpb.javabean.UserBean" id="userBean">
<!-- 經過構造注入設置 經過index 定位設置 -->
<constructor-arg index="0" value="1"/>
<constructor-arg index="1" value="波波烤鴨"/>
<constructor-arg index="2" value="18"/>
</bean>
</beans>
複製代碼
測試結果
有參構造方法不是必須的了,無參方法是必須的!!! set方法注入就是利用對象屬性的set方法給屬性賦值,實際上,至關於首先使用無參構造方法建立一個Book對象,而後調用對象中的set方法給各個屬性賦值。
/**
*
* @author dpb[波波烤鴨]
*
*/
public class UserBean {
private int id;
private String name;
private int age;
/**
* 無參構造方法
*/
public UserBean() {
System.out.println("無參構造方法");
}
public int getId() {
return id;
}
/**
* 設值注入 必須提供對應的setter方法
* @param id
*/
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
/**
* 設值注入 必須提供對應的setter方法
* @param name
*/
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
/**
* 設值注入 必須提供對應的setter方法
* @param age
*/
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "UserBean [id=" + id + ", name=" + name + ", age=" + age + "]";
}
public void say(){
System.out.println("hello ...");
}
}
複製代碼
<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">
<!-- 註冊UserBean -->
<bean class="com.dpb.javabean.UserBean" id="userBean">
<!--經過設值注入的方式注入 -->
<property name="id" value="2"/>
<property name="name" value="bobo烤鴨"/>
<property name="age" value="32"/>
</bean>
</beans>
複製代碼
p名稱空間注入本質上仍是set方法注入,只是寫法不一樣(注意:p名稱空間注入,須要有無參構造方法)。
/**
* p名稱空間注入
* @author dpb[波波烤鴨]
*
*/
public class Person {
private int id;
private String name;
private String address;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
@Override
public String toString() {
return "Person [id=" + id + ", name=" + name + ", address=" + address + "]";
}
}
複製代碼
<!-- 註冊 Person -->
<bean id="person" class="com.dpb.javabean.Person" p:id="3" p:name="鄧澎波" p:address="深圳"/>
複製代碼
這種注入方式瞭解便可,實際開發中使用較少。
對象能夠經過構造方法、set方法或者p名稱空間注入,步驟以下:
/**
* 學生
* @author dpb[波波烤鴨]
*
*/
public class Student {
private int id;
private String name;
// 擁有的 cat
private Cat cat;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Cat getCat() {
return cat;
}
public void setCat(Cat cat) {
this.cat = cat;
}
@Override
public String toString() {
return "Student [id=" + id + ", name=" + name + ", cat=" + cat + "]";
}
}
複製代碼
/**
* 貓
* @author dpb[波波烤鴨]
*
*/
public class Cat {
private int id;
private String color;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
@Override
public String toString() {
return "Cat [id=" + id + ", color=" + color + "]";
}
}
複製代碼
<!-- 配置 cat -->
<bean id="catId" class="com.dpb.javabean.Cat">
<property name="id" value="1"/>
<property name="color" value="red"></property>
</bean>
<!-- 配置 student對象 -->
<bean class="com.dpb.javabean.Student">
<property name="id" value="10"/>
<property name="name" value="波波烤鴨"/>
<!-- 對象注入 -->
<property name="cat" ref="catId"></property>
</bean>
複製代碼
數組和集合的注入方式是一致的,不管是基本數據類型仍是一個引用,注入方式都是同樣。 首先聲明一個對象,對象中包含集合和數組
<!-- 配置 student對象 -->
<bean class="com.dpb.javabean.Student">
<property name="id" value="10"/>
<property name="name" value="波波烤鴨"/>
<!-- 對象注入 -->
<property name="cat" ref="catId"></property>
<!-- List集合注入 -->
<property name="games">
<list>
<value>LOL</value>
<value>DNF</value>
<value>CS</value>
</list>
</property>
<!-- 數組注入 -->
<property name="books">
<list>
<bean class="com.dpb.javabean.Book">
<property name="id" value="1001"/>
<property name="bookName" value="西遊記"/>
</bean>
<bean class="com.dpb.javabean.Book">
<property name="id" value="1002"/>
<property name="bookName" value="紅樓夢"/>
</bean>
</list>
</property>
</bean>
複製代碼
聲明Map屬性,注意屬性的key和value的數據類型須要提早定義好,而後在xml文件中直接使用(xml文件中配置時,key和屬性的值必需要知足聲明的要求,不然就會出錯)。
<property name="score">
<map>
<entry key="數學" value="99"/>
<entry key="英語" value="78"/>
<entry key="化學" value="84"/>
</map>
</property>
複製代碼
properties注入與map注入相似
<property name="props">
<props>
<prop key="userName">admin</prop>
<prop key="password">123</prop>
</props>
</property>
複製代碼