什麼是IoC和DI
IoC(Inversion of Control 控制反轉):是一種面向對象程式設計中的一種設計原則,用來減低計算機代碼之間的耦合度。其基本思想是:借助于“第三方”實作具有依賴關系的對象之間的解耦。
DI(Dependence Injection 依賴注入):将執行個體變量傳入到一個對象中去(Dependency injection means giving an object its instance variables)。
- 控制反轉是一種思想
- 依賴注入是一種設計模式
- IoC架構使用依賴注入作為實作控制反轉的方式
為什麼需要
在沒有IoC之前,我們要在
A
類中使用
B
類,就要在
A
類中
new
出
B
類的執行個體,這樣
A
類和
B
類之間就出現了耦合。
public class A {
private B b = new B();
}
複制
使用了IoC之後,我們就把執行個體化這樣操作交給架構去幫我們做了。
Spring 中的IoC
容器是Spring的核心,Spring容器負責建立應用程式中的bean并通過DI來協調這些對象之間的關系。
Spring容器并不是隻有一個,Spring自帶多個容器的實作,可以歸納為兩種不同的類型:
- bean工廠(
),最簡單的容器,提供基本的DI支援。BeanFactory
- 應用上下文(
),繼承了ApplicationContext
,并提供應用架構級别的服務。BeanFactory
作為開發人員,我們需要告訴Spring哪些對象要作為bean裝配到容器中,bean和bean之間的依賴關系。Spring提供了三種主要的裝配機制:
- 隐式的bean發現機制和自動裝配
- 在Java中進行顯示配置
- 在XML中進行顯示配置
下面我們逐一介紹這三種機制。
自動裝配bean
元件掃描:spring會自動發現應用上下文中所建立的bean
@Component
注解表明該類會作為元件類,并告知Spring要為這個類建立bean。
@Component
public class Dog {
}
複制
@ComponentScan
注解啟用了元件掃描。
@Configuration
@ComponentScan
public class DemoApplication {
}
複制
自動裝配:Spring自動滿足bean之間的依賴
@Autowired
注解可以作用在構造器、方法、屬性上。
@Component
public class Dog {
// 屬性
@Autowired
private Cat cat;
// 構造器
// 從Spring 4.3開始,具有單個構造函數的類可以省略@Autowired注釋
@Autowired
public Dog(Cat cat) {
this.cat = cat;
}
// 方法
@Autowired
public void setCat(Cat cat) {
this.cat = cat;
}
}
複制
在Java中裝配bean
組價配置:聲明一個配置類,并在配置類中配置bean
@Configuration
注解表明這個類是配置類,我們可以在配置類下建立bean。
@bean
注解會告訴Spring這個方法将會傳回一個對象,該對象要注冊為Spring上下文中的bean。
/**
* 普通類
*/
public class BaseBean {
public void p() {
System.out.println("Hello bean");
}
}
/**
* 配置類
*/
@Configuration
public class BeanConfig {
// 這個方法傳回一個對象,Spring會把這個對象注冊為bean
@Bean
public BaseBean getBaseBean() {
return new BaseBean();
}
}
複制
元件注入:在配置類中把被依賴的元件注入另一個元件中
兩種方式注入bean:
- 我們可以直接調用
方法,擷取到對應的元件get
- 在
方法中把被依賴的元件作為參數傳入,Spring在調用這個方法時,會自動為你注入。get
/**
* 普通類
*/
public class BaseBean {
public void p() {
System.out.println("Hello bean");
}
}
/**
* 普通類
*/
public class UserBean {
private BaseBean baseBean;
public UserBean(BaseBean baseBean) {
this.baseBean = baseBean;
}
}
/**
* 配置類
*/
@Configuration
public class BeanConfig {
// 這個方法傳回一個對象,Spring會把這個對象注冊為bean
@Bean
public BaseBean getBaseBean() {
return new BaseBean();
}
/**
* 以下為兩種注入bean的方法
*/
// 方法一:直接調用get方法
@Bean
public UseBean getUseBean() {
return new UseBean(getBaseBean());
}
// 方法二:當做參數傳入,Spring将自動為你注入
@Bean
public UseBean getUseBean(BaseBean baseBean) {
return new UseBean(baseBean);
}
}
複制
通常情況下我們都會使用方法二。
通過XML裝配bean
盡管現在我們已經不再怎麼使用XML裝配bean,但在Spring剛剛出現的時候,XML是描述配置的主要方式,我們還是有必要了解一下的。
在使用JavaConfig的時候,我們建立了一個配置類來裝配bean,而在XML配置中,我們需要建立一個XML檔案,并且要以
<beans>
元素為根。
最為簡單的Spring XML配置如下所示:
<?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">
<!-- 在這裡配置你的bean -->
</beans>
複制
元件配置
以上文的
BaseBean
為例,我們在XML檔案中把它聲明為bean。
<bean id="baseBean" class="com.example.demo.BaseBean" />
複制
元件注入
<bean id="useBean" class="com.example.demo.UseBean"
c:_="baseBean" />
複制
XML的文法我就不再這裡詳述了,有興趣的同學可以自行學習。
總結
本文我們簡單介紹了Spring中的IoC,介紹了Spring中裝配bean的三種方式:自動化配置,基于Java的顯式配置以及基于XML的顯式配置。這些技術都是為了描述Spring應用中的元件以及元件之間的關系。
一般來說我們都會使用自動化配置,盡量避免顯式配置帶來的維護成本。如果不得不使用顯式配置的話,我們優先選擇基于Java的配置,它比基于XML的配置更加強大、類型安全并且易于重構。
參考資料
控制反轉(IoC)與依賴注入(DI)
Spring 實戰
Spring 揭秘