您好,登錄后才能下訂單哦!
一、自動裝配
1、四種類型的自動裝配
類型 | 解釋 | xml 配置 |
---|---|---|
byName | 根據 Bean 的 name 或者 id | <bean id=”bean” class=”…” autowire=”byName”/> |
ByType | 根據 Bean 類型自動裝配 | <bean id=”bean” class=”…” autowire=”byType”/> |
contructor | 根據 Bean 的構造器入參具有相同類型 | 同上 |
Autodetect | 首先使用 contructor,失敗再嘗試 byType | 同上 |
byType 在出現多個匹配項時不會自動選擇一個然是報錯,為避免報錯,有兩種辦法:1.使用<bean>元素的 primary 屬性,設置為首選 Bean,但所有 bean 的默認 primary 都是 true,因此我們需要將所有非首選 Bean 設置為false;2.將 Bean 的autowire-candidate熟悉設置為false,取消 這個 Bean 的候選資格,這個 Bean 便不會自動注入了。
contructor 自動裝配和 byType 有一樣的局限性,當發現多個 Bean 匹配某個構造器入參時,Spring 不會嘗試選擇其中一個;此外,如果一個類有多個構造器都滿足自動裝配的條件,Spring 也不會猜測哪個更合適使用。
2、默認自動裝配
如果需要為 Spring 應用上下文中的每個 Bean(或者其中的大多數)配置相同的 autowire 屬性,可以在根元素<beans>上增加一個 default-autowire 屬性,默認該屬性設置為 none。該屬性只應用于指定配置文件中的所有 Bean,并不是 Spring 上下文中的所有 Bean。
3、混合使用自動裝配和顯式裝配
當我們對某個 Bean 使用了自動裝配策略,并不代表我們不能對該 Bean 的某些屬性進行顯示裝配,任然可以為任意一個屬性配置<property>元素,顯式裝配將會覆蓋自動裝配。但是當使用 constructor 自動裝配策略時,我們必須讓 Spring 自動裝配構造器所有入參,不能使用<constructor-arg>元素進行混合。
二、注解裝配
從 Spring2.5 開始,可以使用注解自動裝配 Bean 的屬性,使用注解允許更細粒度的自動裝配,可選擇性的標注某一個屬性來對其應用自動裝配。Spring 容器默認禁用注解裝配,需要在 Spring 配置中啟用,最簡單的啟用方式是使用 Spring 的 context 命令空間配置中的<context:annotation-config>,如下所示:
<beans ...> <context:annotation-config/> <!-- bean declarations go here --> </beans>
Spring3 支持幾種不同的用于自動裝配的注解:
1、使用@Autowired
@Autowired 用于對被注解對象啟動 ByType 的自動裝配,可用于以下對象:
在使用@Autowired 時有兩種情況會出錯:沒有匹配的 Bean 和存在多個匹配的 Bean,但是都有對應的解決方法。
當沒有匹配 Bean 時,自動裝配會拋出 NoSuchBeanDefinitionException,如果不想拋出可使用 required 屬性,設置為 false 來配置可選的自動裝配,即裝配失敗就不進行裝配,不會報錯。
@Autowired(required=false)
當使用構造器配置時,只有一個構造器可以將 required 屬性設置為 true,其他都只能設置為 false。此外,當使用注解標注多個構造器時,Spring 會從所有滿足裝配條件的構造器中選擇入參最多的那個。
當存在多個 Bean 滿足裝配條件時,Spring 也會拋出 NoSuchBeanDefinitionException 錯誤,為了選擇指定的 Bean,我們可以使用@Qualifier 注解進行篩選:
@Autowired @Qualifier("name1")//篩選名為name1的Bean private TestClass testClass;
除了通過 Bean 的 ID 來縮小選擇范圍,我們還可以通過直接在 Bean 上使用 qualifier 來縮小范圍,限制 Bean 的類型,xml 如下:
<bean class="com.test.xxx"> <qualifier value="stringed"/> </bean>
注解如下:
@Qualifier("stringed") public class xxx{}
還可以創建自定義限定器(Qualifier)
創建自定義限定器只需要使用@Qualifier 注解作為它的源注解即可,如下創建了一個 Stringed 限定器:
@Target({ElementType.FIELD,ElementType.PARAMETER,ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Qualifier public @interface Stringed{}
然后使用它注解一個 Bean:
@Stringed public class Guitar{}
然后就可以進行限定了:
@Autowired @Stringed private Guitar guitar;
2、使用@Inject 自動注入
為統一各種依賴注入框架的編程模型,JCP(Java Community Process)發布的 Java 依賴注入規范,被稱為 JSR-330,從 Spring3 開始,Spring 已經開始兼容該依賴注入模型。
和@Autowired 一樣,@Inject 可以用來自動裝配屬性、方法和構造器。但是@Inject 沒有 required 屬性,因此依賴關系必須存在,如不存在將拋出異常。
JSR-330 還提供另一種注入技巧,注入一個 Provider。Provider 接口可以實現 Bean 引用的延遲注入以及注入 Bean 的多個實例等功能。
例如我們有一個 KnifeJuggler 類需要注入一個或多個 Knife 實例,假設 Knife Bean 的作用域聲明為 prototype,下面的 KnifeJuggler 的構造器將獲得多個 Knife Bean:
private Set<Knife> knifes; @Inject public KnifeJuggler(Provider<Knife> knifeProvider){ knives = new HashSet<Knife>(); for(int i=0;i<5;i++){ knives.add(knifeProvider.get()); } }
相對于@Autowired 所對應的@Qualifier,@Inject 對應的是@Named 注解。事實上 JSR-330 中也有@Qualifier 注解,不過不建議直接使用,建議通過該注解來創建自定義的限定注解,和 Spring 的@Qualifier 創建過程類似。
3、注解中使用表達式
Spring3 中引入的@Value屬性可用來裝配 String 類型的值和基本類型的值。借助 SpEL 表達式,@Value 不光可以裝配硬編碼值還可以在運行期動態計算表達式并裝配,例如下面的:
@Value("#{systemProperties.name}") private String name;
三、自動檢測 Bean
在 Spring 中使用上面說到的<context:annotation-config>,可以做到自動裝配,但還是要在 xml 中申明 Bean。Spring 還有另一個元素<context:component-scan>,元素除了完成自動裝配的功能,還允許 Spring 自動檢測 Bean 和定義 Bean ,用法如下:
<beans ...> <context:component-scan base-package="com.springtest"> </context:component-scan> </beans>
開啟后支持如下注解:
注解 | 解釋 |
---|---|
@Component | 通用的構造型注解,標識類為 Spring 組件 |
@Controller | 標識該類定義為 Spring MVC controller |
@Repository | 標識該類定義為數據倉庫 |
@Service | 標識該類定義為服務 |
使用上述注解是 Bean 的 ID 默認為無限定類名。使用@Component("name")指定 ID。
1、過濾組建掃描
通過為\context:component-scan配置<context:include-filter>和<context:exclude-filter>子元素,我們可以隨意調整掃描行為。下面的配置自動注冊所有的 TestInterface 實現類:
<context:component-scan base-package="com.fxb.springtest"> <context:include-filter type="assignable" expression="com.fxb.springTest.TestInterface"/> </context:component-scan>
其中的 type 和 expression 屬性一起協作來定義組件掃描策略。type 有以下值可選擇:
過濾器類型 | 描述 |
---|---|
annotation | 過濾器掃描使用指定注解所標注的類。通過 expression 屬性指定要掃描的注解 |
assignable | 過濾器掃描派生于 expression 屬性所指定類型的那些類 |
aspectj | 過濾器掃描于 expression 屬性所指定的 AspectJ 表達式所匹配的那些類 |
custom | 使用自定義的 org.springframework.core.type.TypeFilter 實現類,該類由 expression 屬性指定 |
regex | 過濾器掃描類的名稱與 expression 屬性所指定的正則表達式所匹配的類 |
exclude-filter 使用和 include-filter 類似,只是效果相反。
四、使用 Spring 基于 Java 的配置
在 Spring3.0 中幾乎可以不使用 XML 而使用純粹的 Java 代碼來配置 Spring 應用。
首先還是需要極少量的 XML 來啟用 Java 配置,就是上面說到的<context:component-scan>,該標簽還會自動加載使用@Configuration注解所標識的類
@Configuration 注解相當于 XML 配置中的\元素,這個注解將會告知 Spring:這個類包含一個或多個 Spring Bean 的定義,這些定義是使用@Bean 注解所標注的方法
申明一個簡單的 Bean 代碼如下:
@Configuration public class TestConfig{ @Bean public Animal duck(){ return new Ducker(); } }
@Bean 告知 Spring 這個方法將返回一個對象,該對象應該被注冊為 Spring 應用上下文中的一個 Bean,方法名作為該 Bean 的 ID 。想要使用另一個 Bean 的引用也很簡單,如下:
@Bean public Food duckFood(){ return new DuckFood(); } @Bean //通過方法名引用一個Bean,并不會創建一個新的實例 public Animal duck(){ return new Ducker(DuckFood()); }
五、小結
終于寫完了 spring 的最小化配置,對 spring 的各種注解也有了一些了解,再不是之前看到注解一臉莫名其妙了,雖然現在 Springboot 已經幫我們做了零 XML 配置,但覺得還是有必要了解下 XML 配置實現,這樣對 Java 的配置實現理解也會更加深刻。
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持億速云。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。