Spring IoC之DI
Spring IoC之DI(依賴注入)
一、闡述
DI: Dependency(依賴) Injection(注入)
官方解釋
個人理解:
依賴:Bean依賴Spring IoC容器來控制類的建立和時間,以及Bean的生命週期由IoC容器管理,降低類與類之間的依賴,轉而依賴IoC容器
注入:將所需的類、屬性、各種資源…注入到目標類中
好處:Bean之間的依賴交給Ioc容器,降低Bean間的耦合。不用在依賴類中new物件,當被依賴類發生變化時只需要更改Bean的配置資訊即可
二、DI注入方式
1、基於建構函式的依賴注入
A類構造方法中的構造引數依賴B類
SimpleMovieLister.java
package com.hgl.day02;
public class SimpleMovieLister {
private MovieFinder movieFinder;
private MovieDownloader movieDownloader;
public SimpleMovieLister(MovieFinder movieFinder, MovieDownloader movieDownloader){
System.out.println("Injection movieFinder、movieDownloader" );
this.movieFinder = movieFinder;
this.movieDownloader = movieDownloader;
}
public void startWork(){
movieFinder.starFinder();
movieDownloader.startWork();
}
}
MovieFinder.java
package com.hgl.day02;
public class MovieFinder {
public MovieFinder(){
System.out.println("movieFinder's constructor");
}
public void starFinder(){
System.out.println("movieFinder has started");
}
}
MovieDownloader.java
package com.hgl.day02;
public class MovieDownloader {
public MovieDownloader(){
System.out.println("movieDownload's constructor");
}
public void startWork(){
System.out.println("movieDownloader has started");
}
}
xml配置
<bean id="simpleMovieLister" class="com.hgl.day02.SimpleMovieLister">
<constructor-arg ref="movieFinder"/>
<constructor-arg ref="movieDownload"/>
</bean>
<bean id="movieFinder" class="com.hgl.day02.MovieFinder"/>
<bean id="movieDownload" class="com.hgl.day02.MovieDownloader"/>
- 當構造引數有多個物件時,xml配置檔案中當
constructor-arg
標籤要按照構造引數當順序進行注入 - 當注入當為基本資料型別時,可以通過以下方式區別對應的構造引數
使用type屬性對引數對型別進行區分
<constructor-arg type="int" value="2001"/>
<constructor-arg type="java.lang.String" value="Zara"/>
使用index索引對應引數對索引,索引從0開始
<constructor-arg index="0" value="7500000"/>
<constructor-arg index="1" value="42"/>
使用name對應引數的名字
<bean id="exampleBean" class="examples.ExampleBean">
<constructor-arg name="years" value="7500000"/>
<constructor-arg name="ultimateAnswer" value="42"/>
</bean>
參照Spring5.2.7官方文件https://docs.spring.io/spring/docs/5.2.7.RELEASE/spring-framework-reference/core.html#beans-constructor-injection
2、基於setter的依賴注入
通過設定私有屬性,setter方法和getter方法來設值和獲取屬性
SetterMovieLister.java
package com.hgl.day02;
public class SetterMovieLister {
private MovieFinder movieFinder;
private MovieDownloader movieDownloader;
private String message;
public void setMovieFinder(MovieFinder movieFinder) {
this.movieFinder = movieFinder;
}
public void setMovieDownloader(MovieDownloader movieDownloader) {
this.movieDownloader = movieDownloader;
}
public void setMessage(String message) {
this.message = message;
}
public MovieFinder getMovieFinder() {
return movieFinder;
}
public MovieDownloader getMovieDownloader() {
return movieDownloader;
}
public void getMessage() {
System.out.println("message : " + message);
movieFinder.starFinder();
movieDownloader.startWork();
}
}
MovieFinder.java和MovieDownloader.java為構造注入使用的例子
<bean id="setterMovieLister" class="com.hgl.day02.SetterMovieLister">
<property name="movieFinder" ref="movieFinder"/>
<property name="movieDownloader" ref="movieDownload"/>
<property name="message" value="Setter Injection"/>
</bean>
xml配置可使用p 名稱空間進行簡化xml的內容,可改寫成
但是要在beans根目錄下,新增名稱空間xmlns:p="http://www.springframework.org/schema/
p"
<bean id="setterMovieLister" class="com.hgl.day02.SetterMovieLister"
p:movieFinder="movieFinder"
p:movieDownloader="movieDownloder"
p:message="Setter Injection"
/>
官網的另一種方式使用工具包中的Propreties(java.util.Properties)
<bean id="mappings"
class="org.springframework.context.support.PropertySourcesPlaceholderConfigurer">
<!-- typed as a java.util.Properties -->
<property name="properties">
<value>
jdbc.driver.className=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/mydb
</value>
</property>
</bean>
三、內部Bean(Inner Bean)
<bean id="movieFinder" class="com.hgl.day02.MovieFinder"/>
<bean id="movieDownload" class="com.hgl.day02.MovieDownloader"/>
<bean id="setterMovieLister" class="com.hgl.day02.SetterMovieLister">
<property name="movieFinder" ref="movieFinder"/>
<property name="movieDownloader" ref="movieDownload"/>
<property name="message" value="Setter Injection"/>
</bean>
以上bean配置可改寫成:
<bean id="setterMovieLister" class="com.hgl.day02.SetterMovieLister">
<property name="movieFinder">
<bean id="movieFinder" class="com.hgl.day02.MovieFinder"/>
</property>
<property name="movieDownloader">
<bean id="setterMovieLister" class="com.hgl.day02.SetterMovieLister">
</property>
</bean>
idref – 該元素只是將容器中另一個 bean 的(字串值 - 而不是引用)傳遞給 或 元素的一種防錯方法。
<bean id="movieFinder" class="com.hgl.day02.MovieFinder"/>
<bean id="movieDownload" class="com.hgl.day02.MovieDownloader"/>
<bean id="setterMovieLister" class="com.hgl.day02.SetterMovieLister">
<property name="movieFinder">
<idref bean="movieFinder">
</property>
<property name="movieDownloader">
<idref bean="movieDownload">
</property>
</bean>
四、Spring注入集合
List、Set、Map、Properties
InjectionCollection.java
package com.hgl.day02;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
public class InjectionCollection {
Properties addressProps;
List addressList;
Map addressMap;
Set addressSet;
public void setAddressProps(Properties addressProps) {
this.addressProps = addressProps;
}
public void setAddressList(List addressList) {
this.addressList = addressList;
}
public void setAddressMap(Map addressMap) {
this.addressMap = addressMap;
}
public void setAddressSet(Set addressSet) {
this.addressSet = addressSet;
}
public Properties getAddressProps() {
System.out.println("Property Elements :" + addressProps);
return addressProps;
}
public List getAddressList() {
System.out.println("List Elements :" + addressList);
return addressList;
}
public Map getAddressMap() {
System.out.println("Map Elements :" + addressMap);
return addressMap;
}
public Set getAddressSet() {
System.out.println("Set Elements :" + addressSet);
return addressSet;
}
}
package com.hgl.day02;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class CollectionInjectionMainApp {
public static void main(String[] args) {
ApplicationContext context =
new ClassPathXmlApplicationContext("BeansConfigDay02.xml");
InjectionCollection collection = (InjectionCollection) context.getBean("injectionCollection");
collection.getAddressProps();
collection.getAddressList();
collection.getAddressMap();
collection.getAddressSet();
}
}
<bean id="address1" class="com.hgl.day02.Address1"/>
<bean id="address2" class="com.hgl.day02.Address2"/>
<bean id="injectionCollection" class="com.hgl.day02.InjectionCollection">
<property name="addressProps">
<props>
<prop key="address0">廣州</prop>
<prop key="address1">深圳</prop>
<prop key="address2">韶關</prop>
</props>
</property>
<property name="addressList">
<list>
<value>廣州</value>
<ref bean="address1"/>
<ref bean="address2"/>
</list>
</property>
<property name="addressMap">
<map>
<entry key="address0" value="廣州"/>
<entry key="address1" value-ref="address1"/>
<entry key="address2" value-ref="address2"/>
</map>
</property>
<property name="addressSet">
<set>
<value>廣州</value>
<ref bean="address1"/>
<ref bean="address2"/>
</set>
</property>
</bean>
ps:集合之間也可以Spring定義繼承