基于spring的一種代碼拆分的方法

在寫業(yè)務(wù)代碼的時(shí)候我有時(shí)想寫一些策略模式工廠模式類似的代碼拆分業(yè)務(wù),可是在spring下有一些局限性.我們已經(jīng)使用了spring來(lái)管理對(duì)象的初始化,我們就沒(méi)法寫一些類似于

map.put("key",new object())

的代碼.其次同一接口下多個(gè)實(shí)現(xiàn)類需要使用

@Qualifier("a")
@Qualifier("b")

來(lái)區(qū)分,那么最終我們的代碼大概會(huì)寫成這個(gè)樣子

public class WxEventHandleFactory {

    @Autowired
    @Qualifier("scan")
    private WxEventHandle scanHandle;

    @Autowired
    @Qualifier("subscribe")
    private WxEventHandle subscribeHandle;

    @Autowired
    @Qualifier("unsubscribe")
    private WxEventHandle unsubscribeHandle;

    public WxEventHandle getHandle(String event) {
        if (WxEventType.SUBSCRIBE.getCode().equals(event)) {
            return subscribeHandle;
        } else if (WxEventType.UNSUBSCRIBE.getCode().equals(event)) {
            return unsubscribeHandle;
        } else if (WxEventType.SCAN.getCode().equals(event)) {
            return scanHandle;
        }
        return null;
    }
}

這段代碼就是根據(jù)微信公眾號(hào)不同的消息,拆分了不同處理代碼.不好的點(diǎn)就是我們的策略方法會(huì)不斷的膨脹的,但這也不是不能接受,我在flink的某個(gè)連接redis做狀態(tài)存儲(chǔ)的開源項(xiàng)目下也看到過(guò)更大的類似方法,不過(guò)是用switch 拆分罷了.

那么我們有沒(méi)有更好的辦法呢?

我們可不可以通過(guò)一些類似標(biāo)記的方式給我們業(yè)務(wù)類打上獨(dú)有的標(biāo)記?

注解是一個(gè)不錯(cuò)的方案

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface CallBack {

    TypeEnum[] value();
}

這里value為什么是一個(gè)數(shù)組呢,因?yàn)槲蚁M鄠€(gè)策略使用同一個(gè)類處理.

我們?cè)趺磸膕pring的管理中獲取這些被我們標(biāo)記的類呢?

bean實(shí)例化后會(huì)注入ApplicationContext

@Component
public class MyBean {
    @Autowired
    private ApplicationContext context;
}

接下來(lái)我們只需要將標(biāo)有@CallBack的類統(tǒng)一使用數(shù)據(jù)結(jié)構(gòu)保存起來(lái),每次根據(jù)不同TypeEnum獲取即可,其次為了方便調(diào)用,我們所有的業(yè)務(wù)類肯定需要實(shí)現(xiàn)相同的方法

public interface BaseStrategyCallBack {
    void doMethod(MyContext myContext);
}

@PostConstruct(bean初始化前執(zhí)行,相當(dāng)于init)

@Component
public class FactoryStrategy {

    private static Map<TypeEnum, BaseStrategyCallBack> map = new ConcurrentHashMap<>();

    @Autowired
    private ApplicationContext context;

    public static BaseStrategyCallBack createDoMethod(TypeEnum typeEnum) {
        return map.get(doTypeEnum);
    }


    @PostConstruct
    public void init() {
        Map<String, Object> beansMap = context.getBeansWithAnnotation(CallBack.class);
        beansMap.values()
                .forEach(i -> {
                    OrderCallBack doTypeAnnotation = i.getClass().getAnnotation(CallBack.class);
                    for(ItemTypeEnum e : doTypeAnnotation.value()){
                        map.put(e, (BaseStrategyCallBack) i);
                    }
                });
    }
}

編寫業(yè)務(wù)類

@Log4j2
@Service
@CallBack(TypeEnum.test)
public class StrategyTest implements BaseStrategyCallBack {

    @Override
    public void doMethod(MyContext myContext) {
        //業(yè)務(wù)邏輯
    }
}

調(diào)用

FactoryStrategy.createDoMethod(typeEnum).doMethod(myContext);

至此我們就實(shí)現(xiàn)了基于spring的代碼拆分,根據(jù)不同的枚舉獲取不同的業(yè)務(wù)類.

ps:我平時(shí)是不看spring相關(guān)書籍去學(xué)習(xí)的,當(dāng)工作中需要的時(shí)候可能會(huì)點(diǎn)進(jìn)去看一丟丟源碼也是屬于看過(guò)就忘.但是有一點(diǎn)就是一定要去看官方文檔,畢竟spring的文檔算是開源項(xiàng)目里最完善的一批了.理解了ioc,aop.你就有了思考的脈絡(luò),剩下東西,我愿意稱為機(jī)制而不是技術(shù),所以機(jī)制的東西,在不會(huì)的時(shí)候去看文檔查一查就好.況且現(xiàn)在還有chatgpt,查文檔更是一絕.其次我也很少看設(shè)計(jì)模式相關(guān)的東西,因?yàn)橹灰阈闹杏蓄?接口,抽象類的概念,那你就可以梳理代碼的結(jié)構(gòu),以不變應(yīng)萬(wàn)變我覺(jué)得才是更好的方式.當(dāng)然這是我個(gè)人極端的想法,設(shè)計(jì)模式還是需要看的,只是我目前還沒(méi)有多余的時(shí)間,之前一直都是寫一些底層原理的文章,是因?yàn)槲覀€(gè)人比較癡迷這些東西.最近嘗試寫一些比較業(yè)務(wù)的東西,展示一下工作中的一些思路.

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容