Spring——@Autowired註解和啟動自動掃描的三種方式
引用文章地址:
https://my.oschina.net/HeliosFly/blog/203902(重點推薦!!!!!)
http://wiki.jikexueyuan.com/project/spring/annotation-based-configuration/spring-autowired-annotation.html
https://www.tianmaying.com/tutorial/spring-auto-wiring
http://www.cnblogs.com/liuzy2014/p/6692781.html
http://blog.csdn.net/baple/article/details/17891755
@Autowired註解代碼定義如下:
@Target()
@Retention(RetentionPolicy.RUNTIME)
@Documentedpublic@interfaceAutowired{booleanrequired()defaulttrue;}
從上述定義中,我們可以得出@Autowired註解只有一個屬性即required屬性,此屬性的默認值為true,即默認情況下它要求依賴對象必須存在,如果不存在會出現空指針等錯誤;如果允許為null,可以設置它required屬性為false.其中@Autowired註解和標註的變數的類的set和get方法無關,自動裝配的實現並不是依賴set方法的方式實現的.在xml中利用
這種方式是依賴對應類的set方法的方式實現的 @Autowired註解使用之前首先確定判斷一下此處能夠使用@Autowired註解.
一、 @Autowired註解使用場景介紹
二、 @Autowired註解所涉及的原理部分
其實在啟動spring IoC時,容器自動裝載了一個AutowiredAnnotationBeanPostProcessor後置處理器,當容器掃描到@Autowied、@Resource或@Inject時,就會在IoC容器自動查找需要的bean,並裝配給該對象的屬性
注意事項:
在使用@Autowired時,首先在容器中查詢對應類型的bean
如果查詢結果剛好為一個,就將該bean裝配給@Autowired指定的數據
如果查詢的結果不止一個,那麼@Autowired會根據名稱來查找。
如果查詢的結果為空,那麼會拋出異常。解決方法時,使用required=false
上述過程說明了@Autowired註解默認是按照類型裝配注入的,默認情況下它要求依賴對象必須存在如果允許為null,可以設置它required屬性為false,如果想按照名稱來轉配注入,則需要結合@Qualifier一起使用;
三、 處理使用@Autowired註解出現自動裝配的歧義性問題
使用@Autowired註解的過程中,如果出現NoUniqueBeanDefinitionException異常,大多是因為自動裝配或者其他方式裝配所導致的歧義性.即一個介面存在兩個以上的實現類.即在自動裝配的時候,可能出現因重名問題導致的NoUniqueBeanDefinitionException異常.
@Autowired是按類型進行裝配的,那麼我一個介面UserInterface,有多個實現類
AImpl(@service(name="userInterface1")),BImpl(@service(name="userInterface2")
等等這些實現類都加入了Spring容器,當在一個類中使用如下語句:
@Autowired
privateIUserInterface userInterface;
在下面列舉一下了一下,上述問題以及類似的裝配歧義性解決問題方法.
方法一
首先加上註解@Qualifier來區分不同的實例.通過在實現介面的類上通過value屬性去命名不同的名稱,對於@Repository、@Service 和 @Controller 和 @Component四個註解都有類似value屬性可以設置,例如:
@Service(value="userServiceImpl")
publicclassUserServiceImplimplementsIUserService{
}
@Autowired
@Qualifier("userServiceImpl")
privateIUserService userServiceImpl;
方法二
因為一個介面存在兩個以上的實現類,也可以通過標識首選哪個bean,來解決歧義性問題.例如:
@Component@PrimarypublicclassUserServiceImplimplementsIUserService{}
此時,如果引用到了IUserService介面的實現類注入,則首先注入@Promary註解標註的類,但是此時有一個問題,在同一個介面的實現類中,你只能使用一次@Primary,如果對於AImpl和BImpl都使用了@primary,則還是會發生裝配的歧義性.此時,建議使用(1)的方式來解決歧義性問題.
方法三
最後一種方式,可以使用自定義的限定符註解,但是此種情況很少出現,再次就不做介紹,可自行百度.
四、 Spring通過哪些特性實現自動裝配的?
Spring從兩個角度來實現自動化裝配:
(1)組件掃描(component scanning):Spring會自動發現應用上下文中所創建的bean.
(2)自動裝配(autowiring):Spring自動滿足bean之間的依賴.
組件掃描和自動裝配組合在一起就能發揮出強大的威力,它們能夠將你的顯示配置降低到最少.
五、@Autowired和@Resource之間的區別
在本文只列舉出@Autowired和@Resource之間常見的表面區別,至於區別的原因需要查看Spring官方文檔中的@Autowired註解實現方式和Java中@Resource註解實現方式.
(1)、@Autowired默認是按照類型裝配注入的,默認情況下它要求依賴對象必須存在如果允許為null,可以設置它required屬性為false,如果想按照名稱來轉配注入,則需要結合@Qualifier一起使用;
(2)、@Resource默認是按照名稱來裝配注入的,只有當找不到與名稱匹配的bean才會按照類型來裝配注入;
(3)、@Resource註解是由J2EE提供,而@Autowired是由spring提供,故減少系統對spring的依賴建議使用@Resource的方式;
(4)、@Resource和@Autowired都可以書寫標註在欄位或者該欄位的setter方法之上
(5)、@Resource默認按照名稱裝配,當找不到與名稱匹配的bean才會按照類型裝配,可以通過name屬性指定,如果沒有指定name屬 性,當註解標註在欄位上,即默認取欄位的名稱作為bean名稱尋找依賴對象,當註解標註在屬性的setter方法上,即默認取屬性名作為bean名稱尋找 依賴對象.注意:如果沒有指定name屬性,並且按照默認的名稱仍然找不到依賴的對象時候,會回退到按照類型裝配,但一旦指定了name屬性,就只能按照名稱裝配了.
六、Spring是如何啟動自動掃描的
在這裡列舉出三種啟動自動掃描的方式.
方式一:此種情況下,針對比較特殊的情形,即項目中運用了SpringBoot,則可以利用@SpringBootApplication註解的方式啟動自動掃描功能.
importorg.springframework.boot.SpringApplication;
importorg.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
publicclassApplication{publicstaticvoidmain(String[] args) { SpringApplication.run(Application.class, args); }}
方式二:通過XML配置方式,啟動自動掃描功能.XML配置方式
方式三:通過Java配置方式,啟動自動掃描功能.
在上面的鏈接中給出了一個具體的樣例可以參照實現理解一下。
其中關於@Configuration和@ComponentScan兩個註解:
(2)@ComponentScan表示開啟Spring Beans掃描,類似於XML配置,這裡也可以可以設置basePackages屬性。
如果@ComponentScan註解沒有顯示去給其他的屬性賦值的話,比如此處給basePackages賦值了,如果沒有的話,@ComponentScan註解會掃描與配置類相同的包.
注意:關於@Repository、@Service 和 @Controller 和 @Component四個註解的使用情形
在持久層、業務層和控制層分別採用 @Repository、@Service 和 @Controller 對分層中的類進行注釋,而用 @Component 對那些比較中立的類進行注釋.這裡就是說把這個類交給Spring管理,重新起個名字叫userManager,由於不好說這個類屬於哪個層面,就用@Component.
七、Spring存在幾種裝配方式?
目前,在Spring中,一共提供三種裝配方式:
在實際項目中,一般是上述三種裝備方式都可能存在,不過基於標註的自動裝配方式是在項目中最常用的.通過給Java類增加相應的標註,就能夠啟用Spring隱式的Bean發現機制,並自動完成裝配過程.我們在開發中應該儘可能使用自動裝配,足以應付開發中的絕大多數情況.在某些情況下,基於XML配置和基於Java配置的顯式裝配會有用武之地,比如實例化一個第三方庫中的Bean.這種情況下,Java配置和XML配置我們優先使用Java配置,因為這是一種類型安全的方式,能夠在編譯時就儘早發現錯誤.
關於上述所說的類型安全可以這樣理解:如果使用字元串的形式,在xml中類名或其他硬編碼方式提供的信息,在開發時是發現不了的,會在運行時拋出異常。而使用Java配置形式,類名或其他硬編碼配置信息寫錯的話,編譯時就會提示錯誤,比如Eclipse中就會提示找不到類的錯誤信息,這就避免了這種情況下的運行時異常,因此是更加安全的.
TAG:全球大搜羅 |