动态

详情 返回 返回

【面向接口編程(IOP)典型場景】底層組件如何實現回調通知上層應用系統? - 动态 详情

本文介紹了在賬務插件開發中,如何通過“面向接口編程”實現異步轉賬完成後的回調通知機制。通過定義回調接口 TransferCallback,賬務組件在異步操作完成後可通知上層應用進行後續業務處理。文章提供了純 Java 和 Spring 兩種實現方式的代碼示例,展示了接口在插件化架構中的重要作用,體現了面向接口編程在解耦與擴展方面的優勢。




我們在開發一個賬務插件(sby-plugin-accounting),將賬户的充、轉、提等記賬功能進行封裝,實現複用。

其中,針對賬户的轉賬操作,為提高程序性能,我們使用“同步+異步”的處理方式:轉出賬户的扣款在工作線程中執行,而轉入賬户的入賬則採用異步的方式。

那麼,現在問題來了,當異步轉賬完成後,如何通知上層應用層?

沒錯,達芬奇密碼是:面向接口編程(Interface-Oriented Programming, IOP)。通過接口定義插件契約,這是在插件化架構中典型的解決方案。————異步轉賬完成後,依賴回調接口。上層應用系統如果需要關注異步轉賬完成的結果,則實現回調接口,進行特定的業務處理。

下面我們列舉關鍵代碼,來説明如何基於OOP的IOP思想,通過回調接口實現記賬完成的回調通知。下圖程序結構是個demo,其中,子包 biz代表上層應用系統的業務邏輯,component 代表底層賬務組件;主包 componentdemocomponentdemospring代表純java版、spring版這兩種實現方式。

【面向接口編程(IOP)典型場景】底層組件如何實現回調通知上層應用系統?

🍀純java版

1. 插件層

●插件中的回調接口TransferCallback

TransferCallback是一個interface類,定義了一個方法onTransferSuccess,這是該插件與上層應用系統建立邏輯關係的紐帶。插件中的異步轉賬調用這個interface,上層應用系統按需實現這個interface

package jstudy.componentdemo.component;

public interface TransferCallback {
    void onTransferSuccess(String transferOrderNo);
}

●插件中的轉賬服務類AccountTransferService

下面AccountTransferService是賬務轉賬服務類(記賬邏輯均為示意代碼)。其中,

  • 定義了TransferCallback字段,並對外暴露了setter操作;
  • accountingForTos方法中依賴了這個字段的實例,達到轉賬完成後進行回調通知的目的。
package jstudy.componentdemo.component;

// 轉賬記賬service
@Slf4j
public class AccountTransferService {
    private AccountingService accountingService = new AccountingService();
    @Setter
    private TransferCallback transferCallback;

    private static final Executor threadPool = ...;

    public void accounting(AccountTransfer accountTransfer) {
        log.info("轉賬記賬開始");
        AccountingRequest accountingRequest = new AccountingRequest(accountTransfer.getTransferOrderNo(), accountTransfer.getFrom(), accountTransfer.getTransferAmount(), true);
        accountingService.accounting(accountingRequest);

        // 通過異步為轉賬的收款方入賬
        threadPool.execute(() -> {
            accountingForTos(accountTransfer);
        });
    }

    private void accountingForTos(AccountTransfer accountTransfer) {
        var listTo = accountTransfer.getTos();// 收款方集合
        for (var entry: listTo.entrySet()) {
            AccountingRequest accountingRequest = new AccountingRequest(accountTransfer.getTransferOrderNo(), entry.getKey(), entry.getValue(), false);
            accountingService.accounting(accountingRequest);
        }

        boolean isImplementTransferCallback = transferCallback != null;
        log.info("上層應用是否實現了轉賬回調:{}", isImplementTransferCallback);
        if (isImplementTransferCallback) {
            transferCallback.onTransferSuccess(accountTransfer.getTransferOrderNo());
        }
    }
}

2. 上層應用層

下面TransferOrderService是應用層的 轉賬單service 類。該類同時實現了TransferCallback接口。
關鍵的控制在它的構造器中,決定是否要開啓轉賬完成通知。

// 業務轉賬單service
@Slf4j
public class TransferOrderService implements TransferCallback {
    private AccountTransferService accountTransferService;

    public TransferOrderService() {
        accountTransferService = new AccountTransferService();
//        accountTransferService.setTransferCallback(this);//是否開啓轉賬完成通知
    }

    public void transfer() {
        log.info("轉賬單記賬");

        AccountTransfer accountTransfer = new AccountTransfer();
        accountTransfer.setTransferOrderNo("T202508000001")
                .setFrom("A")
                .setTransferAmount(50.00);
        accountTransfer.setTos(ImmutableMap.of(
                "B", 10.00,
                "C", 40.00));
        accountTransferService.accounting(accountTransfer);
    }

    @Override
    public void onTransferSuccess(String transferOrderNo) {
        log.info("=========當前是在應用層,進行轉賬完成後的業務處理,轉賬單號={}", transferOrderNo);
        log.info("=========已向收款人發送到賬通知短消息");
    }
}

程序運行結果

  • 開啓了轉賬完成回調
08:58:49.927 [j.c.biz.TransferOrderService] - 轉賬單記賬
08:58:49.935 [j.c.component.AccountTransferService] - 轉賬記賬開始
08:58:49.938 [j.c.component.AccountingService] - AccountingService->記賬完成. 業務單號=T202508000001, accountNo=A, amount=50.00
08:58:49.949 [j.c.component.AccountingService] - AccountingService->記賬完成. 業務單號=T202508000001, accountNo=B, amount=-10.00
08:58:49.949 [j.c.component.AccountingService] - AccountingService->記賬完成. 業務單號=T202508000001, accountNo=C, amount=-40.00
08:58:49.949 [j.c.component.AccountTransferService] - 上層應用是否實現了轉賬回調:true
08:58:49.949 [j.c.biz.TransferOrderService] - =========當前是在應用層,進行轉賬完成後的業務處理,轉賬單號=T202508000001
08:58:49.949 [j.c.biz.TransferOrderService] - =========已向收款人發送到賬通知短消息
  • 未開啓轉賬完成回調
08:58:49.927 [j.c.biz.TransferOrderService] - 轉賬單記賬
08:58:49.935 [j.c.component.AccountTransferService] - 轉賬記賬開始
08:58:49.938 [j.c.component.AccountingService] - AccountingService->記賬完成. 業務單號=T202508000001, accountNo=A, amount=50.00
08:58:49.949 [j.c.component.AccountingService] - AccountingService->記賬完成. 業務單號=T202508000001, accountNo=B, amount=-10.00
08:58:49.949 [j.c.component.AccountingService] - AccountingService->記賬完成. 業務單號=T202508000001, accountNo=C, amount=-40.00
08:58:49.949 [j.c.component.AccountTransferService] - 上層應用是否實現了轉賬回調:false



🍀Spring版

1. 插件層

●插件中的轉賬服務類AccountTransferService

下面AccountTransferService是賬務轉賬服務類。通過@Autowired(required = false)來注入TransferCallback實例。

package jstudy.componentdemo.component;


// 轉賬記賬service
@Service
@Slf4j
public class AccountTransferService {
    @Autowired
    private AccountingService accountingService;
    @Autowired(required = false)
    private TransferCallback transferCallback;

    public void accounting(AccountTransfer accountTransfer) {
        ...
        // 通過異步為轉賬的收款方入賬
        threadPool.execute(() -> {
            accountingForTos(accountTransfer);
        });
    }

    private void accountingForTos(AccountTransfer accountTransfer) {
        ...
        if (isImplementTransferCallback) {
            transferCallback.onTransferSuccess(accountTransfer.getTransferOrderNo());
        }
    }
}

2. 上層應用層

下面TransferOrderService是應用層的 轉賬單service 類。

由於該類是由 Spring 容器託管的 bean,並且實現了TransferCallback接口,因此,這表示開啓了轉賬完成的回調通知。

如果不開啓,則不實現TransferCallback接口即可。

// 業務轉賬單service
@Service
@Slf4j
public class TransferOrderService implements TransferCallback {
    @Autowired
    private AccountTransferService accountTransferService;


    public void transfer() {
        ...
    }

    @Override
    public void onTransferSuccess(String transferOrderNo) {
        ...
    }
}
user avatar cikiss 头像
点赞 1 用户, 点赞了这篇动态!
点赞

Add a new 评论

Some HTML is okay.