原創:微信公眾號
碼農參上
,歡迎分享,轉載請保留出處。
哈嘍大家好啊,我是Hydra。
Spring作為專案中不可缺少的底層框架,提供的最基礎的功能就是bean
的管理了。bean
的注入相信大家都比較熟悉了,但是有幾種不太常用到的集合注入方式,可能有的同學會不太瞭解,今天我們就通過範例看看它的使用。
首先,宣告一個介面:
public interface UserDao {
String getName();
}
然後定義兩個類來分別實現這個介面,並通過@Component
註解把bean
放入spring容器中:
@Component
public class UserDaoA implements UserDao {
@Override
public String getName() {
return "Hydra";
}
}
@Component
public class UserDaoB implements UserDao {
@Override
public String getName() {
return "#公眾號:碼農參上";
}
}
準備工作完成後,我們看看幾種不同型別的集合注入方式。
首先來看Map
型別的注入,直接在Service
中注入一個Map
,key
為字串型別,value
為上面定義的介面型別。
@Service
@AllArgsConstructor
public class UserMapService {
final Map<String, UserDao> userDaoMap;
public Map<String,UserDao> getDaos(){
return userDaoMap;
}
}
通過介面測試,檢視這個Map
中的內容:
可以看到,Map
中的value
是實現了介面的範例物件,key
則是beanName
,可以通過@Component
的value
屬性進行自定義。
修改UserDaoA
,指定名稱:
@Component(value = "Hydra")
public class UserDaoA implements UserDao {...}
可以看到,key
的值發生了改變:
在Service
中,這次注入泛型為介面UserDao
型別的List
。
@Service
@AllArgsConstructor
public class UserListService {
private final List<UserDao> userDaoLists;
public List<UserDao> getDaos(){
return userDaoLists;
}
}
測試這個方法,檢視List
中的內容,是我們放入容器中的兩個bean
:
我們知道,List
是一個有序的資料結構,那麼如果想要修改List
中bean
的排序,該如何做呢?
很簡單,修改注入到spring容器中的兩個bean
,為它們新增@Order
註解並指定載入順序,數位越小越優先載入。
@Component
@Order(1)
public class UserDaoA implements UserDao {……}
@Component
@Order(-1)
public class UserDaoB implements UserDao {……}
修改完成後,再進行測試,可以看到bean
的順序發生了改變:
同樣,也可以使用無序的Set
注入bean
,泛型指定為介面型別。
@Service
@AllArgsConstructor
public class UserSetService {
private final Set<UserDao> userDaoSet;
public Set<UserDao> getDaos(){
return userDaoSet;
}
}
檢視Set
中的元素,和List
相同,只不過順序變為無序,不會因為@Order
註解的值而改變:
最後,我們再來看一下陣列注入的方式:
@Service
@AllArgsConstructor
public class UserArrayService {
private final UserDao[] userDaoArray;
public UserDao[] getDaos(){
return userDaoArray;
}
}
檢視陣列中的元素:
並且,和List
比較類似的,陣列中bean
的排序會受到@Order
註解數值的影響,有興趣的同學可以自己嘗試一下。
瞭解了這幾種注入方式後,再簡單提一下它的使用場景。例如,我們可以用Map
注入實現策略模式,來替換程式碼中繁雜的if/else
判斷。例如,原始的程式碼中判斷邏輯可能是這樣的:
public String choice(String name){
if (name.equals("auth")){
return "Hydra";
}else if (name.equals("official")){
return "#公眾號:碼農參上";
}
return null;
}
使用策略模式進行改造,首先修改beanName
:
@Component(value = "auth")
public class UserDaoA implements UserDao {
@Override
public String getName() {
return "Hydra";
}
}
@Component(value = "official")
public class UserDaoB implements UserDao {
@Override
public String getName() {
return "#公眾號:碼農參上";
}
}
再修改Servie
中的方法,一行程式碼即可實現原有的if/else
判斷:
@Service
@AllArgsConstructor
public class TestService {
final Map<String, UserDao> userDaoMap;
public String choice2(String name){
return userDaoMap.get(name).getName();
};
}
可能在這個例子中,這種寫法的優點體現的不十分明顯,但是當你有一個非常長的if/else
判斷時,這種模式能使你的程式碼看上去簡潔很多,並且符合程式碼按照功能拆分的原則。
同理,如果你已經通過@Order
註解定義好了bean
的載入順序,也可以將它理解為bean
的優先順序,例如我想要呼叫優先順序最高的符合型別的bean
的方法,那麼完全可以這樣寫:
@Service
@AllArgsConstructor
public class TestService {
final List<UserDao> userDaoLists;
public String choiceFirst(){
return userDaoLists.get(0).getName();
};
}
通過上面兩個簡單的例子可以看到,集合注入的方式使用起來非常靈活,我們可以在實際使用中,結合各種設計模式,寫出實用而優雅的程式碼。
那麼,這次的分享就到這裡,我是Hydra,下篇文章再見。
作者簡介,
碼農參上
,一個熱愛分享的公眾號,有趣、深入、直接,與你聊聊技術。歡迎新增好友,進一步交流。