控制反轉與依賴注入
阿新 • • 發佈:2019-01-21
【 Spring IoC Container 使用步驟 (非Web環境) 】
1、Configuration metadata
可以使用 XML 檔案,比如 container.xml
可以使用註解
2、建立容器:
// 在 指定配置檔案時可以使用 Ant 風格的萬用字元
final String configLocations = "classpath:org/**/container.xml";
ApplicationContext container = new ClassPathXmlApplicationContext( configLocations ) ;
ApplicationContext 是個介面
final String configLocations = "classpath:org/**/container.xml";
AbstractApplicationContext container = new ClassPathXmlApplicationContext(configLocations) ;
AbstractApplicationContext 是個抽象類,其中定義了 close() 方法
3、從容器中獲取 Bean
ClassName x = container.getBean( "bean-id" , ClassName.class ) ;
其中 bean-id 是指 XML 檔案中 或 註解中 為 Bean 指定的 id
其中 ClassName 是指 Bean 的型別,比如 org.malajava.container.Person
4、關閉容器 (優秀是一種習慣)
container.close() ; // AbstractApplicationContext 是個抽象類,其中定義了 close() 方法
【 控制反轉 ( Inversion of Control , IoC ) 】
使用一個 Person 型別的物件:
[ Java ]
Date date = new Date();
Person p = new Person();
p.setId( 9527 ) ;
p.setName( "華安" );
p.setGender( '男' );
p.setBirthdate( date ) ; // 引用另外一個物件
System.out.println( p.getId() + " : " + p.getName() + " , " + p.getGender() );
[ IoC ]
<bean id="date" class="java.util.Date" />
<bean id="person" class="org.malajava.container.Person">
<property name="id" value="9527" />
<property name="name" value="華安" />
<property name="gender" value="男" />
<property name="birthdate" ref="date" />
</bean>
Person p = container.getBean( "person" , Person.class );
System.out.println( p.getId() + " : " + p.getName() + " , " + p.getGender() );
【 依賴注入 ( Dependency Injection , DI ) 】
1、基於 setter 的注入方式 ( Spring 支援 ) [主要應用方向]
對於"簡單型別"來說可以使用以下形式注入:
<property name = "屬性名" value = "字面量" />
或
<property name="屬性名" >
<value>字面量</value>
</property>
所謂"簡單型別"是指:
8種基本資料型別及其包裝類型別的屬性
byte --> Byte
short ---> Short
int ---> Integer
long --> Long
float ---> Float
double ---> Double
char ----> Character
boolean ---> Boolwan
java.lang.String
對於其他的引用型別的屬性來說,要使用以下形式注入:
<property name = "屬性名" ref = "所引用的Bean的id" />
或
<property name="屬性名" >
<ref bean="所引用的Bean的id" />
</property>
Spring Framework 3.x 開始支援 p 名稱空間 ( namespace ):
首先需要在 xml 檔案中引入 p 名稱空間:
xmlns:p="http://www.springframework.org/schema/p"
對於 "簡單型別" 的屬性來說,可以使用以下形式注入:
<bean id="...." class="...." p:屬性名 = "屬性值" />
對於其他的引用型別的屬性來說,要使用以下形式注入:
<bean id="...." class="...." p:屬性名-ref = "屬性值" />
2、基於構造方法的注入方式 ( Spring 支援 )
<bean id="student" class="org.malajava.injection.Student" >
<constructor-arg name="name" value="郭襄" />
<constructor-arg name="id" value="1" />
<constructor-arg name="number" value="1003" />
<constructor-arg name="gender" value="女" />
<constructor-arg name="birthdate" ref="date" />
<constructor-arg name="married" value="false" />
</bean>
注意:
a>、如果一個類中提供了帶引數的構造方法,建議建立不帶引數的那個構造方法
b>、在使用 constructor-arg 時,可以使用 index 、type 、name 來確定為那個引數注入值
c>、對於 "簡單型別" 來說,使用 value 屬性即可注入相應值;
對於其他引用型別來說使用 ref 屬性引用容器中已經宣告的其他Bean的id
3、基於介面方式的注入( Spring 預設不支援 )
【 Bean 的建立方式 ( bean creation ) 】
1、使用構造方法建立 Bean 例項
比如:
使用無參構造:
<bean id="date" class="java.util.Date" />
使用帶引數的構造:
<bean id="student" class="org.malajava.injection.Student" >
<constructor-arg name="name" value="郭襄" />
<constructor-arg name="id" value="1" />
<constructor-arg name="number" value="1003" />
<constructor-arg name="gender" value="女" />
<constructor-arg name="birthdate" ref="date" />
<constructor-arg name="married" value="false" />
</bean>
2、靜態工廠方法
public class Car {
private String brand ;
public static Car getInstance() {
System.out.println( "Car.getInstance()" );
Car c = new Car();
return c ;
}
}
<bean id="car"
class="org.malajava.creation.Car"
factory-method="getInstance"
p:brand="BYD" />
<bean id="calendar"
class="java.util.Calendar"
factory-method="getInstance" />
3、例項工廠方法
public class Bus {
private String brand ;
}
public class BusFactory {
public Bus create() {
Bus b = new Bus();
b.setBrand( "比亞迪" );
return b ;
}
}
<bean id="busFactory" class="org.malajava.creation.BusFactory" />
<bean id="bus" class="org.malajava.creation.Bus" factory-bean="busFactory" factory-method="create" >
<property name="brand" value="比亞迪" />
</bean>
4、FactoryBean
a>、需要有一個類實現了 org.springframework.beans.factory.FactoryBean 介面(並實現其中的抽象方法)
並指定 該實現類所建立的 物件的型別 (在型別引數中指定)
public class ShipFactoryBean implements FactoryBean<Ship>{
@Override
public Ship getObject() throws Exception { // 負責建立 Ship 型別的物件
return null;
}
@Override
public Class<?> getObjectType() { // 返回 所建立物件的型別
return null;
}
}
b>、在 FactoryBean 實現類內部的 getObject 方法用來建立 <T> 型別的物件
<!-- 如果 class 所制定的 類 實現了 FactoryBean 介面,
那麼 這個配置所建立的物件 是由 該 FactoryBean 實現類的 getObject 方法所返回的物件 -->
<bean id="ship" class="org.malajava.creation.ShipFactoryBean" />