依賴注入的配置
Spring的依賴注入分為
- 基于建構式的依賴注入
- 基于setter方法的依賴注入
基于建構式的依賴注入
<!-- 通過構造器引數索引方式依賴注入 -->
<bean id="byIndex" >
<constructor-arg index="0" value="https://www.cnblogs.com/54chensongxia/p/Hello World!"/>
<constructor-arg index="1" value="https://www.cnblogs.com/54chensongxia/p/1"/>
</bean>
<!-- 通過構造器引數型別方式依賴注入 -->
<bean id="byType" >
<constructor-arg type="java.lang.String" value="https://www.cnblogs.com/54chensongxia/p/Hello World!"/>
<constructor-arg type="int" value="https://www.cnblogs.com/54chensongxia/p/2"/>
</bean>
<!-- 通過構造器引數名稱方式依賴注入 -->
<bean id="byName" >
<constructor-arg name="message" value="https://www.cnblogs.com/54chensongxia/p/Hello World!"/>
<constructor-arg name="index" value="https://www.cnblogs.com/54chensongxia/p/3"/>
</bean>
<!-- 通過靜態的工廠方法注入 -->
<bean id="byName" factory-method="getBean">
<constructor-arg name="message" value="https://www.cnblogs.com/54chensongxia/p/Hello World!"/>
<constructor-arg name="index" value="https://www.cnblogs.com/54chensongxia/p/3"/>
</bean>
基于setter方法的依賴注入
<bean >
<property name="message" value="https://www.cnblogs.com/54chensongxia/p/Hello"/>
<property name="index" value="https://www.cnblogs.com/54chensongxia/p/1"/> //value中的值全部是字串形式,如果轉換出錯會報例外
</bean>
<bean id="Hello2" >
<property name="msg" ref="message"/> //msg屬性是一個類物件
</bean>
回圈依賴:創建Bean A需要Bean B,創建Bean B需要Bean C,創建Bean C需要Bean A 這樣就形成了回圈依賴, Spring的解決方案:Spring創建Bean的時候會維護一個池,在創建A的時候會去池中查找A是否在池子中,假如發現就拋出回圈依賴例外,
避免依賴注入時的回圈依賴:可以使用setter方式注入,不要使用構造器形式的注入,
依賴配置常見列子
常量值注入配置
<bean id="myDataSource" destroy-method="close">
<!-- results in a setDriverClassName(String) call -->
<property name="driverClassName" value="https://www.cnblogs.com/54chensongxia/p/com.mysql.jdbc.Driver"/>
<property name="url" value="https://www.cnblogs.com/54chensongxia/p/jdbc:mysql://localhost:3306/mydb"/>
<property name="username" value="https://www.cnblogs.com/54chensongxia/p/root"/>
<property name="password" value="https://www.cnblogs.com/54chensongxia/p/masterkaoli"/>
</bean>
注入其他Bean
這邊分別給出了一個參考當前容器和參考父容器中Bean的列子,
<bean id="Hello2" >
<property name="msg"> //msg屬性是一個類物件
<ref bean="message"/> //參考同一個容器中id="message"的Bean
</property>
</bean>
<!-- 參考父容器中的Bean -->
<!-- in the parent context -->
<bean id="accountService" >
<!-- insert dependencies as required as here -->
</bean>
<!-- in the child (descendant) context -->
<bean id="accountService" <!-- bean name is the same as the parent bean -->
>
<property name="target">
<ref parent="accountService"/> <!-- notice how we refer to the parent bean -->
</property>
<!-- insert other configuration and dependencies as required here -->
</bean>
注入內部Bean
內部bean:這種bean一般只讓某個外部bean使用(和內部類相似),不讓容器中的其他Bean使用,
<bean id="outer" >
<property name="target">
<!-- this is the inner bean -->
<bean >
<property name="name" value="https://www.cnblogs.com/54chensongxia/p/Fiona Apple"/>
<property name="age" value="https://www.cnblogs.com/54chensongxia/p/25"/>
</bean>
</property>
</bean>
集合的注入
集合類的注入建議使用util命名空間
<util:map id="myMap" key-type="java.lang.String" value-type="java.lang.String">
<entry key="key1" value="https://www.cnblogs.com/54chensongxia/p/chen"/>
<entry key="key2" value="https://www.cnblogs.com/54chensongxia/p/zhao"/>
</util:map>
<util:list id="myList" value-type="java.lang.String">
<value>chen</value>
<value>zhao</value>
</util:list>
<util:set id="mySet" value-type="java.lang.String" scope="singleton">
<value>chen</value>
<value>zhao</value>
</util:set>
<util:properties id="myProp" location="classpath:xx.properties"/>
null值和空字串的注入
<bean >
<property name="message"><null/></property> //null值
<property name="index" value=""/> //空字串
</bean>
使用depends-on屬性
depends-on屬性用來指定bean的初始化順序,這個屬性只對scope是單列的bean生效,
<!--在實體化beanOne之前先實體化manager和accountDao這兩個bean-->
<bean id="beanOne" depends-on="manager,accountDao">
<property name="manager" ref="manager" />
</bean>
<bean id="manager" />
<bean id="accountDao" />
懶加載
bean的定義中有一個lazy-init這個屬性,用來設定單列bean在容器初始化后是否實體化這個bean,默認情況下容器是會實體化所有單例bean的,我們也建議這么做,因為這樣能在容器初始化階段就發現bean配置是否正確,如果一個Bean按照下面的設定,lazy-init被設定為true那么它不會被容器預初始化,只有在被使用的時候才被初始化,但是如果有一個單列類依賴了這個Bean,那么這個被設定成懶加載的Bean還是會被預初始化,
<bean id="lazy" lazy-init="true"/>
如果想設定全域的單例Bean都不要預先初始化,那么可以在xml中做如下設定:
<beans default-lazy-init="true">
<!-- no beans will be pre-instantiated... -->
</beans>
Autowiring相關
當我們要往一個bean的某個屬性里注入另外一個bean,我們會使用property +ref標簽的形式,但是對于大型專案,假設有一個bean A被多個bean參考注入,如果A的id因為某種原因修改了,那么所有參考了A的bean的ref標簽內容都得修改,這時候如果使用autowire="byType",那么參考了A的bean就完全不用修改了,
<!--autowire的用法如下,對某個Bean配置autowire模式 -->
<!--和給Bean的屬性添加@AutoWired注解的效果一致-->
<bean id="auto" autowire="byType"/>
autowire的幾種模式:
- no模式:也是默認模式,這種模式下不會進行自動屬性注入,需要我們自己通過value或者ref屬性進行配置;
- byName模式:通過屬性的名稱自動裝配,Spring會在容器中查找名稱與bean屬性名稱一致的bean,并自動注入到bean屬性中,當然bean的屬性需要有setter方法,例如:bean A有個屬性master,master的setter方法就是setMaster,A設定了autowire="byName",那么Spring就會在容器中查找名為master的bean通過setMaster方法注入到A中;
- byType:通過型別自動裝配(注入),Spring會在容器中查找類(Class)與bean屬性類一致的bean,并自動注入到bean屬性中,如果容器中包含多個這個型別的bean,Spring將拋出例外,如果沒有找到這個型別的bean,那么注入動作將不會執行;
- constructor:類似于byType,但是是通過建構式的引數型別來匹配,假設bean A有建構式A(B b, C c),那么Spring會在容器中查找型別為B和C的bean通過建構式A(B b, C c)注入到A中,與byType一樣,如果存在多個bean型別為B或者C,則會拋出例外,但時與byType不同的是,如果在容器中找不到匹配的類的bean,將拋出例外,因為Spring無法呼叫建構式實體化這個bean;
- default : 采用父級標簽(即beans標簽的default-autowire屬性)的配置,
需要注意的是上面這5中方式注入都需要我們提供相應的setter方法,通過@Autowired的方式不需要提供相應的setter方法,
自動裝配的缺點
- 屬性和建構式引數設定中的顯式依賴項會覆寫自動裝配;
將Bean排除自動裝配
如果按照下面的方式配置了Bean,那么這個Bean將不會作為自動裝配的候選Bean,但是autowire-candidate自會對byType形式的自動注入生效,如果我們是通過byName的形式進行自動注入,那么還是能注入這個Bean,
<bean id="auto" autowire="byType" autowire-candidate="false"/>
如果我們只想讓某些Bean作為自動裝配的候選Bean,那么可以進行全域設定,如果做了下面的配置,那么只有id為bean1和bean2的Bean才會成為自動裝配的候選Bean,同時default-autowire-candidates的值支持正則運算式形式,但是強烈建議不要配置這個選項的值,使用默認的配置就行,
<beans default-autowire-candidates="bean1,bean2">
</beans>
方法注入(單例依賴原型Bean)
我們在配置bean的時候首先要考慮這個bean是要配置成單例模式還是其他模式, 在我們的應用中,絕大多數類都是單例類,當單例類參考單例類,或者原型類參考原型類、單例類時,我們只要像普通的配置方式就行了,但是當一個單例類參考原型類時,就會出現問題,這種情況可以使用下面的方式進行注入,
@Service
@Scope("prototype")
public class MyService1 {
public void service() {
System.out.println(this.toString() + ":id");
}
}
@Service
public abstract class MyService {
private MyService1 service1;
public void useService(){
service1 = createService1();
service1.service();
}
@Lookup("myService1")
public abstract MyService1 createService1();
}
//也可以這樣配置bean
<bean id="serviceC" >
<lookup-method bean="serviceD" name="createService"/>
</bean>
<bean id="serviceD" scope="prototype"/>
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/165591.html
標籤:Java
