概念
IOC(Inversion of Control)
其思想是反轉資源獲取的方向. 傳統的資源查找方式要求組件向容器發起請求查找資源. 作爲迴應, 容器適時的返回資源. 而應用了 IOC 之後, 則是容器主動地將資源推送給它所管理的組件, 組件所要做的僅是選擇一種合適的方式來接受資源. 這種行爲也被稱爲查找的被動形式
DI(Dependency Injection) — IOC 的另一種表述方式
即組件以一些預先定義好的方式(例如: setter 方法)接受來自如容器的資源注入. 相對於 IOC 而言,這種表述更直接
通過反射機制配置Bean
注入的方式
- 構造函數方式 (類中需要帶參數的構造函數)
<constructor-arg></constructor-arg>
- 屬性方式 (類中需要無參數的構造函數)
<property></property>
abstract屬性爲true的時候,IOC容器不會實例化對象,如果value屬性含有特殊字符,需要使用<![CDATA[]]>包裹起來
集合
- 屬性爲list集合
<property name="group"> <list> <ref bean="developer"></ref> <ref bean="developer"></ref> </list> </property>
- 屬性爲props
<property name="adminEmails"> <props> <prop key="administrator">[email protected]</prop> <prop key="support">[email protected]</prop> <prop key="development">[email protected]</prop> </props> </property>
- 屬性爲map
<property name="someMap"> <map> <entry key="an entry" value="just some string"/> <entry key ="a ref" value-ref="myDataSource"/> </map> </property>
- 屬性爲set
<property name="someSet"> <set> <value>just some string</value> <ref bean="myDataSource" /> </set> </property>
通過工廠方法配置Bean
靜態工廠方法
Factory類本身不需要實例化,這個Factory類中提供了1個靜態方法來生成bean對象
public class StaticAddressFactory {
private static Map<String, Address> addressMap = new HashMap<String, Address>() ;
static {
addressMap.put("JINAN", new Address("JINAN", "SHILIHE"));
addressMap.put("QINGDAO", new Address("QINGDAO", "SIFANG"));
}
public static Address getAddress(String name){
return addressMap.get(name);
}
}
實例工廠方法
Factory類本身需要實例化
public class SigletonAddressFactory {
public Map<String, Address> getAddressMap() {
return addressMap;
}
public void setAddressMap(Map<String, Address> addressMap) {
this.addressMap = addressMap;
}
private Map<String, Address> addressMap = new HashMap<String, Address>() ;
public Address getAddress(String name){
return this.addressMap.get(name);
}
}
Factory Bean模式配置Bean
Factory Bean模式
比工廠方法模式更常見,Factory Bean工廠類必須實現spring提供的FactoryBean的接口
重寫以下三個方法:
- getObject()
這個就是你想利用工廠類生產的bean對象, 通常在裏面new 1個 對象就ok - getObjectType()
你必須指明上面bean的對象的class - isSingleton
這個方法決定了這個bean是否單例的
案例
public class MyAddressFactory implements FactoryBean<Address> {
private String city;
private String street;
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public String getStreet() {
return street;
}
public void setStreet(String street) {
this.street = street;
}
@Override
public Address getObject() throws Exception {
return new Address(this.city, this.street);
}
@Override
public Class<?> getObjectType() {
return Address.class;
}
@Override
public boolean isSingleton() {
return false;
}
}
通過FactoryBean方式,從IOC容器裏面bean,通過FactoryBean的getObject返回指定的bean,property: MyAddressFactory的屬性設置
通過註解方式注入Bean
- 組件掃描(component scanning): Spring 能夠從 classpath 下自動掃描, 偵測和實例化具有特定註解的組件.
- 特定組件包括:
@Component: 基本註解, 標識了一個受 Spring 管理的組件
@Respository: 標識持久層組件
@Service: 標識服務層(業務層)組件
@Controller: 標識表現層組件 -
對於掃描到的組件, Spring 有默認的命名策略: 使用非限定類名, 第一個字母小寫. 也可以在註解中通過 value 屬性值標識組件的名稱
-
在組件類上使用了特定的註解之後, 還需要在 Spring 的配置文件中聲明 <context:component-scan> :
base-package 屬性指定一個需要掃描的基類包,Spring 容器將會掃描這個基類包裏及其子包中的所有類.
當需要掃描多個包時, 可以使用逗號分隔.-
如果僅希望掃描特定的類而非基包下的所有類,可使用 resource-pattern 屬性過濾特定的類
- <context:include-filter> 子節點表示要包含的目標類
- <context:exclude-filter> 子節點表示要排除在外的目標類
- <context:component-scan> 下可以擁有若干個 <context:include-filter> 和 <context:exclude-filter> 子節點
-
Scope("prototype")
當bean增加註解@Scope("prototype"),那麼就是獲得的多實例的bean
命名策略
對於掃描到的組件, Spring 有默認的命名策略:
- 使用非限定類名, 第一個字母小寫.
- 也可以在註解中通過 value 屬性值標識組件的名稱
<!--在context中聲明需要檢測的bean目錄,同時會檢測目錄的子目錄-->
<context:component-scan base-package="com.annotation"></context:component-scan>
<!--
掃描base-package目錄子的某一個子目錄,可以利用resource-pattern
<context:component-scan base-package="com.annotation" resource-pattern="子目錄/*.class"></context:component-scan>
-->
bean的作用域
singleton
單例模式
prototype
每次取出的bean對象都需要實例化