Java 8 對Field injection的處理
在之前的文章裡Field injection is not recommended介紹了為什麼要儘量避免Field injection, 這篇文章主要介紹如何解決該問題.
使用Field injection的程式碼像下面
class controller{
@Auowired
private A a;
...
}
Java8 之前, 推薦使用的是constructor injection, 我們的處理變為
class controller{
private A a;
@Auowired
public controller(A a){
this.a=a;
}}
改成上方式的話, new controller的時候, 就必須使用引數. 這對於使用IDE的程式設計師來說, 可以很好的避免了bug(空指標). 然而, 自由性被限制, 當我們不確定某些屬性是否一定要實現時, construct method 要寫若干個, 程式碼量也增加了.
class controller{
private A a;
...
@Auowired
public controller(A a){
this.a=a;
}
public controller(A a,B b){
...
}
public controller(A a,B b,C c){
...
}}
上述程式碼, 如果對映到程式設計思想, 也就是COC(convention over configuration), 我們希望要修改的地方得到修改即可.
綜上 Java 8 之前的field injection 和 constructor injection的優點, 我們可以使用optional類.
實現程式碼如下:
class controller{
@Autowired
private Optional<A> a;
}
這裡有兩個問題, 1.原始碼中使用到A類的如何改? 2.Optional會自動匹配到A介面的實現類嗎?
1)原始碼中使用到A類的如何改?
原來的程式碼
methodA(){
if(a!=null) dosomething;
}
methodB(){
if(a!=null) return something;
}
對應則是
methodA(){
if(a.isPresent()) dosomething;
}
methodB(){
if(a.isPresent() ) return something;
}
methodB(){
a.get();
}
當然, 也可以如下
methodA(){
a.map(a->dosomething);
}
methodB(){
a.ifPresent(a->dosomething);
}
方法若干… 函式式的方法, 基本都對應一個場景, 需要多看Javadoc
2)Optional會自動匹配到A介面的實現類嗎?
答: 會
摘自IBM
使用 @Autowired 註解進行裝配,只能是根據型別進行匹配。@Autowired 註解可以用於 Setter 方法、建構函式、欄位,甚至普通方法,前提是方法必須有至少一個引數。@Autowired 可以用於陣列和使用泛型的集合型別。然後 Spring 會將容器中所有型別符合的 Bean 注入進來。@Autowired 標註作用於 Map 型別時,如果 Map 的 key 為 String 型別,則 Spring 會將容器中所有型別符合 Map 的 value 對應的型別的 Bean 增加進來,用 Bean 的 id 或 name 作為 Map 的 key。
上述文章說道, map是可以匹配得到的, 所以這種機制同樣適用於optional.
測試程式碼如下:
@Autowired
Map<String, Object> a;
@RequestMapping(value = "/iaaa")
public void a()
System.out.println(a.size());
}