沒想到吧,Spring中還有一招集合注入的寫法

2022-07-06 12:00:36

原創:微信公眾號 碼農參上,歡迎分享,轉載請保留出處。

哈嘍大家好啊,我是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注入

首先來看Map型別的注入,直接在Service中注入一個Mapkey為字串型別,value為上面定義的介面型別。

@Service
@AllArgsConstructor
public class UserMapService {
    final Map<String, UserDao> userDaoMap;

    public Map<String,UserDao> getDaos(){
        return userDaoMap;
    }
}

通過介面測試,檢視這個Map中的內容:

可以看到,Map中的value是實現了介面的範例物件,key則是beanName,可以通過@Componentvalue屬性進行自定義。

修改UserDaoA,指定名稱:

@Component(value = "Hydra")
public class UserDaoA implements UserDao {...}

可以看到,key的值發生了改變:

List注入

Service中,這次注入泛型為介面UserDao型別的List

@Service
@AllArgsConstructor
public class UserListService {
    private final List<UserDao> userDaoLists;

    public List<UserDao> getDaos(){
        return userDaoLists;
    }
}

測試這個方法,檢視List中的內容,是我們放入容器中的兩個bean

我們知道,List是一個有序的資料結構,那麼如果想要修改Listbean的排序,該如何做呢?

很簡單,修改注入到spring容器中的兩個bean,為它們新增@Order註解並指定載入順序,數位越小越優先載入。

@Component
@Order(1)
public class UserDaoA implements UserDao {……}
@Component
@Order(-1)
public class UserDaoB implements UserDao {……}

修改完成後,再進行測試,可以看到bean的順序發生了改變:

Set注入

同樣,也可以使用無序的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,下篇文章再見。

作者簡介,碼農參上,一個熱愛分享的公眾號,有趣、深入、直接,與你聊聊技術。歡迎新增好友,進一步交流。