Java:學習@Autowired
原貼收藏在IT老兵驛站。
前言
使用SpringMVC,現在不可避免要接觸註解,會遇到@Autowired,查詢了google,找到這篇文章,摘錄下來,做一些筆記。為什麼這樣呢?因為至少來說,以當前的理解,自己來寫,不太可能超越這篇文章,我也不想像很多人那樣搞所謂“二次原創”,其實不還是抄襲,只是針對了判定抄襲的規則來做文章,不耍這樣的小聰明,沒有意義。
本篇選取主要的部分翻譯一下,具體的過程可以參考程式碼,本文的英文難度不高,可以嘗試著讀一讀。
正文
1. Overview
Starting with Spring 2.5, the framework introduced a new style of Dependency Injection driven by @Autowired
In this tutorial, we will look at how to enable autowiring, various ways to wire in beans, making beans optional, resolving bean conflicts using @Qualifier annotation along with potential exception scenarios.
Spring2.5之後,可以使用@Autowired 註解來實現DI(依賴注入),這個詞本身的英文意思就是自動裝配。
2. Enabling @Autowired Annotations
If you are using Java based configuration in your application you can enable annotation-driven injection by using AnnotationConfigApplicationContext to load your spring configuration as below:
1 2 3 |
|
As an alternative, in Spring XML, it can be enabled by declaring it in Spring XML files like so: <context:annotation-config/>
想使用註解,現需要配置Spring可以支援註解,有兩種方式,一個是在程式碼中,一個是在XML中,這個涉及到另外一些知識點,作者這裡是假設讀者是知道這些的,不明白的話,需要去查一查。
3. Using @Autowired
Once annotation injection is enabled, autowiring can be used on properties, setters, and constructors.
可以用在屬性、setter方法和構造器上。
3.1. @Autowired on Properties
The annotation can be used directly on properties, therefore eliminating the need for getters and setters:
1 2 3 4 5 6 7 |
|
1 2 3 4 5 6 7 |
|
In the above example, Spring looks for and injects fooFormatter when FooService is created.
如何用在屬性上。
3.2. @Autowired on Setters
The @Autowired annotation can be used on setter methods. In the below example, when the annotation is used on the setter method, the setter method is called with the instance of FooFormatter when FooServiceis created:
1 2 3 4 5 6 7 8 9 |
|
如何用在方法上。
3.3. @Autowired on Constructors
The @Autowired annotation can also be used on constructors. In the below example, when the annotation is used on a constructor, an instance of FooFormatter is injected as an argument to the constructor when FooService is created:
1 2 3 4 5 6 7 8 9 |
|
如何用在構造器方法上。
4. @Autowired and Optional Dependencies
Spring expects @Autowired dependencies to be available when the dependent bean is being constructed. If the framework cannot resolve a bean for wiring, it will throw the below-quoted exception and prevent the Spring container from launching successfully:
1 2 3 4 5 |
|
To avoid this from happening, a bean can optional be specified as below:
1 2 3 4 5 6 |
|
如果沒有找到響應的bean,又不想系統停止載入,參考上面的寫法。
5. Autowire Disambiguation
By default, Spring resolves @Autowired entries by type. If more than one beans of the same type are available in the container, the framework will throw a fatal exception indicating that more than one bean is available for autowiring.
@Autowired是根據型別來進行裝備的。但是會存在同一型別內有多個備選bean,這個時候,框架會丟擲一個致命錯誤----這種問題倒是暫時還沒有遇到過,下面講述了三種解決方案。
5.1. Autowiring by @Qualifier
The @Qualifier annotation can be used to hint at and narrow down the required bean:
1 2 3 4 5 6 7 |
|
1 2 3 4 5 6 7 |
|
1 2 3 4 5 6 |
|
Since there are two concrete implementations of Formatter available for the Spring container to inject, Spring will throw a NoUniqueBeanDefinitionException exception when constructing the FooService:
|
This can be avoided by narrowing the implementation using a @Qualifier annotation:
1 2 3 4 5 6 7 |
|
By specifying the @Qualifier with the name of the specific implementation, in this case as fooFormatter, we can avoid ambiguity when Spring finds multiple beans of the same type.
Please note that the value of the @Qualifier annotation matches with the name declared in the @Component annotation of our FooFormatter implementation.
使用@Qualifier 註解來標識誰是合格的。
5.2. Autowiring by Custom Qualifier
Spring allows us to create our own @Qualifier annotation. To create a custom Qualifier, define an annotation and provide the @Qualifier annotation within the definition as below:
1 2 3 4 5 6 7 8 9 |
|
Once defined, the FormatterType can be used within various implementations to specify custom value:
1 2 3 4 5 6 7 8 |
|
1 2 3 4 5 6 7 8 |
|
Once the implementations are annotated, the custom Qualifier annotation can be used as below:
1 2 3 4 5 6 7 8 |
|
The value specified in the @Target annotation restrict where the qualifier can be used to mark injection points.
In the above code snippet, the qualifier can be used to disambiguate the point where Spring can inject the bean into a field, a method, a type, and a parameter.
5.3. Autowiring by Name
As a fallback Spring uses the bean name as a default qualifier value.
So by defining the bean property name, in this case as fooFormatter, Spring matches that to the FooFormatter implementation and injects that specific implementation when FooService is constructed:
1 2 3 4 5 6 |
|
使用名字來自動裝配。
6. Conclusion
Although both @Qualifier and bean name fallback match can be used to narrow down to a specific bean, autowiring is really all about injection by type and this is how best to use this container feature.
The source code of this tutorial can be found in the GitHub project – this is an Eclipse based project, so it should be easy to import and run as it is.
總結
老外的文章講的真清楚,他們會對讀者負責,很認真地把所有問題講清楚,不像很多國人,哪怕是很多好像挺有名的教授出的書,都是“言簡意賅”,看著好費勁,給人一種高高在上的感覺。當年讀清華嚴蔚敏出的《資料結構》,讀著就非常費勁,後來看大師出的《演算法導論》,反而容易理解,中國人怎麼總就是這麼高傲呢。
參考
https://www.baeldung.com/spring-autowire
https://stackoverflow.com/questions/1018797/can-you-use-autowired-with-static-fields 介紹了靜態域能不能自動裝配