自動裝配(autowiring):有助於減小甚至消除配置<property>元素和<constructor-arg>元素,讓Spring自動識別如何裝配Bean的依賴關係。java
自動檢測(autodiscovery):比自動裝配更進一步,讓Spring可以自動識別哪些類須要被配置成Spring Bean,從而減小對<bean>元素的使用。正則表達式
byName——把與Bean的屬性具備相同名字(或者ID)的其餘Bean自動裝配到Bean的對應屬性中。若是沒有跟屬性的名字相匹配的Bean,則該屬性不進行裝配。spring
byType——把與Bean的屬性具備相同類型的其餘Bean自動裝配到Bean的對應屬性中。若是沒有跟屬性的名字相匹配的Bean,則該屬性不進行裝配。express
constructor——把與Bean的構造器入參具備相同類型的其餘Bean自動裝配到Bean構造器的對應入參中。ui
autodetect——首先嚐試使用constructor進行自動裝配。若是失敗,再嘗試使用byType進行自動裝配。spa
byName自動裝配code
——爲屬性自動裝配ID與該屬性同名的Beancomponent
例:xml
假設存在一個Instrumentalist類包含屬性song、instrument,如下是手動裝配Bean的方式。對象
<bean id="saxophone" class="com.roger.spring.beans.Saxophone" /> <bean id="kenny" class="com.roger.spring.beans.Instrumentalist"> <property name="song" value="Jingle Bells" /> <property name="instrument" ref="saxophone" /> </bean>
若是要利用byName自動裝配,就須要在使用<bean>元素定義Saxophone的時候,將Bean的id設置爲I和nstrumentalist屬性instrument同名的字面值。 經過配置autowire屬性就能夠利用此信息自動裝配 kenny 的 instrument 屬性了。
<bean id="instrument" class="com.roger.spring.beans.Saxophone" /> <bean id="kenny" class="com.roger.spring.beans.Instrumentalist" autowire="byName"> <property name="song" value="Jingle Bells" /> </bean>
byType自動裝配
——Spring會尋找哪個Bean的類型與屬性的類型相同。
侷限:若是Spring尋找到多個Bean,它們的類型與須要自動裝配的屬性的類型都相匹配,這時候,Spring不會猜想哪個Bean更適合自動裝配,而是選擇拋出異常。因此,應用只容許存在一個Bean與須要自動裝配的屬性類型相匹配。
解決裝配歧義的問題:能夠爲自動裝配標識一個首選,或者取消某個Bean自動裝配的候選資格。
標識首選
利用<bean>的primary屬性, 默認爲true,所以要達到標識首選的目的,須要將其餘候選的primary屬性都設爲false。
取消候選
將<bean>的autowire-candidate屬性設爲false。
constructor自動裝配
——在Bean聲明中,不須要<constructor-arg>元素了
侷限:a. 具備和byType自動裝配相同的侷限,當發現多個Bean匹配某個構造器入參時,Spring不會猜想哪一個更適合;
b. 若是一個類有多個構造器,它們都知足自動裝配的條件時,Spring也會猜想哪一個更適合。
默認自動裝配
利用<beans>屬性default-autowire進行設置,默認爲none,表示都不使用自動裝配。能夠利用<bean>元素的autowire屬性來覆蓋<beans>的默認自動裝配策略。
使用註解方式容許更細粒度的自動裝配,能夠選擇性地標註某一個屬性來對其應用自動裝配。
Spring容器默認禁用註解裝配
xml配置中啓用註解,利用context命名空間中<context:annotation-config>元素,以下所示:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context:"http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http:..www.springframework.org/schema/context http:..www.springframework.org/schema/context/spring-context.xsd"> <context:annotation-config /> </beans>
Spring支持集中不一樣的用於自動裝配的註解:
Spring自帶的@Autowired註解
JSR-330的@Inject註解
JSR-250的@Resource註解
@Autowired 默認是經過byType方式進行自動裝配的,經過結合@Qualifier註解能夠經過匹配Bean的id進行自動裝配。
如:
經過@Qualifier註解將範圍縮小,嘗試將id爲"guita"的bean注入。
@Autowired @Qualifier("guita") private Instrument instrument;
a、@Resource默認是按照名稱來裝配注入的,只有當找不到與名稱匹配的bean纔會按照類型來裝配注入;
b、@Autowired默認是按照類型裝配注入的,若是想按照名稱來轉配注入,則須要結合@Qualifier一塊兒使用;
c、@Resource註解是由J2EE提供,而@Autowired是由Spring提供,故減小系統對spring的依賴建議使用
@Resource的方式;
d、@Resource和@Autowired均可以書寫標註在字段或者該字段的setter方法之上
即便<context:annotation-config>元素有助於徹底消除Spring配置中的<property>和<constructor-arg>元素,可是仍要使用<bean>元素顯示定義Bean。
所以,藉助<context:component-scan>元素,除了完成與<context:annotation-config>同樣的工做,還容許Spring自動檢測Bean和定義Bean。中意味着不使用<bean>元素,Spring應用中的大多數(或全部)Bean都可以實現定義和裝配。
還能夠經過<context:component-scan>元素的base-package屬性標識<context:component-scan>元素會掃描指定的包及其全部子包。
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context:"http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http:..www.springframework.org/schema/context http:..www.springframework.org/schema/context/spring-context.xsd"> <context:component-scan base-package="com.roger.spring.beans"> </context:component-scan> </beans>
默認狀況下,<context:component-scan>查找使用構造型(stereotype)註解所標註的類。
這些特殊註解以下:
@Component——經過的構造型註解,標識該類爲Spring組件
@Controller——標識將該類定義爲Spring MVC controller
@Repository——標識將該類定義爲數據倉庫
@Service——標識將該類定義爲服務
使用@Component標註的任意自定義註解
Spring掃描發現@Component註解所標註的類,並自動地將它註冊爲Spring Bean,Bean的ID默認爲無限定類名(如:Person Bean的id爲person)。
也可使用@Component("Roger")方式來指定Bean的id。
經過爲<context:component-config>配置子元素<context:include-filter>或者<context:exclude-filter>來調整掃描行爲。
<context:include-filter>的type和expression屬性一塊兒來定義組件掃描策略。
過濾器類型 | 描述 |
annotation |
過濾器掃描使用指定註解所標註的那些類,經過expression屬性指定要掃描的註解 |
assignable | 過濾器掃描派生於expression屬性所指定類型的那些類 |
aspectj | 過濾器掃描與expression屬性所指定的AspectJ表達式所匹配的那些類 |
custom | 使用自定義的org.springframework.core.type.TypeFilter實現類,該類由expression屬性指定 |
regex | 過濾器掃描類的名稱與expression屬性所指定的正則表達式所匹配的那些類 |
例如:
<context:component-scan base-package="com.roger.spring.beans"> <context:include-filter type="assignable" expression="com.roger.spring.Address" /> </context:component-scan>
用極少許的xml來啓用java配置:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context:"http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http:..www.springframework.org/schema/context http:..www.springframework.org/schema/context/spring-context.xsd"> <context:component-scan base-package="com.roger.spring.beans"> </context:component-scan> </beans>
<context:component-scan>自動註冊那些使用某種構造型(stereotype)註解所標註的Bean。
同時,也會自動加載使用@Configuration註解所標註的類。
在基於java的配置裏使用@Configuration註解的java類,等價於xml配置中的<beans>元素。
@Configuration註解做爲一個標識告知Spring:這個類將包含一個或多個Spring Bean的定義。
這些Bean的定義是使用@Bean註解所標註的方法。
例如:
有一個Person基類,Teacher類繼承Person類,如下,聲明一個簡單的id爲roger的Teacher Bean。
import org.springframework.context.annotation.Configuration; @Configuration public class SpringConfig { //Bean declaration methods go here //聲明一個簡單的Bean @Bean public Person roger() { return new Teacher(); } }
@Bean告知Spring這個方法將返回一個對象,該對象應該被註冊爲Spring應用上下文中的一個Bean,方法名做爲Bean的id。
例如:
注入一個引用
import org.springframework.context.annotation.Configuration; @Configuration public class SpringConfig { //Bean declaration methods go here @Bean public Address address() { return new Address(); } @Bean public Person roger() { return new Teacher(address()); } }
注意:在Spring的java配置中,經過聲明方法引用一個Bean並不等同於調用該方法。經過@Bean註解標註address()方法,要在其餘Bean的聲明方法中引用這個方法時,Spring都會攔截方法的調用,並嘗試在應用上下文中查找該Bean,而不是讓方法建立一個新的實例。