前言
偶然的機會發(fā)現(xiàn)spring有個spring-plugin矾麻,官網對它的介紹是
Spring Plugin provides a more pragmatic approach to plugin development by providing the core flexibility of having plugin implementations extending a core system's functionality but of course not delivering core OSGi features like dynamic class loading or runtime installation and deployment of plugins. Although Spring Plugin thus is not nearly as powerful as OSGi, it serves a poor man's requirements to build a modular extensible application.
大意就是Spring插件提供了一種更實用的插件開發(fā)方法,它提供了插件實現(xiàn)擴展核心系統(tǒng)功能的核心靈活性吏颖,但當然不提供核心OSGi功能输莺,如動態(tài)類加載或運行時安裝和部署插件甫男。盡管Spring插件因此不如OSGi強大攘已,但它滿足了窮人構建模塊化可擴展應用程序的需求。
本文就來聊下如何使用spring插件來實現(xiàn)策略模式
使用spring-plugin插件實現(xiàn)策略模式步驟
1澜共、在項目中的pom引入spring-plugin
<dependency>
<groupId>org.springframework.plugin</groupId>
<artifactId>spring-plugin-core</artifactId>
<version>2.0.0.RELEASE<version>
</dependency>
注: springboot 2.2以下版本默認已經集成spring-plugin-core向叉,因此無需指定版本號。不過集成的版本號比較低嗦董,而且部分方法與高版本不兼容
2母谎、定義一個實體類,這個實體類后邊插件綁定插件類型會用到
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class SmsRequest implements Serializable {
private Map<String,Object> metaDatas;
private String to;
private String message;
private SmsType smsType;
}
3京革、定義插件實現(xiàn)org.springframework.plugin.core.Plugin接口
public interface SmsPlugin extends Plugin<SmsRequest> {
SmsResponse sendSms(SmsRequest smsRequest);
}
4奇唤、配置激活插件
@EnablePluginRegistries(SmsPlugin.class)
@Configuration
public class SmsPluginActiveConfig {
}
5、定義插件的具體實現(xiàn)類
@Component
public class AliyunSmsPlugin implements SmsPlugin {
@Override
public SmsResponse sendSms(SmsRequest smsRequest) {
System.out.println("來自阿里云短信:" + smsRequest);
return SmsResponse.builder()
.code("200").message("發(fā)送成功")
.success(true).result("阿里云短信的回執(zhí)").build();
}
@Override
public boolean supports(SmsRequest smsRequest) {
return SmsType.ALIYUN == smsRequest.getSmsType();
}
}
注:該具體插件必須是spring的bean
6匹摇、插件使用
在業(yè)務項目注入
@Autowired
private PluginRegistry<SmsPlugin,SmsRequest> pluginRegistry;
通用調用pluginRegistry.getPluginFor方法拿到具體插件
示例:
@RequiredArgsConstructor
public class SmsService {
private final PluginRegistry<SmsPlugin,SmsRequest> pluginRegistry;
public SmsResponse sendSms(SmsRequest smsRequest){
Optional<SmsPlugin> smsPlugin = pluginRegistry.getPluginFor(smsRequest);
return smsPlugin.orElseThrow(() -> new SmsException("Sms plugin is not binder with type : 【" + smsRequest.getSmsType() + "】"))
.sendSms(smsRequest);
}
}
7冻记、測試
@Test
public void testAliyunSms(){
SmsRequest smsRequest = SmsRequest.builder()
.message("模擬使用阿里云短信發(fā)送")
.to("136000000001")
.smsType(SmsType.ALIYUN)
.build();
SmsResponse smsResponse = smsService.sendSms(smsRequest);
Assert.assertTrue(smsResponse.isSuccess());
System.out.println(smsResponse);
}
總結
本文主要通過一個模擬短信發(fā)送的示例,演示如何通過spring-plugin來實現(xiàn)策略模式来惧。如果我們對擴展性有要求除了spi,我們也可以考慮使用spring-plugin演顾。不過基于spring-plugin擴展時供搀,要注意具體的插件實現(xiàn)類要為spring的bean,不然插件會找不到
更多詳細例子可以查看官網
https://github.com/spring-projects/spring-plugin
demo鏈接
https://github.com/lyb-geek/springboot-learning/tree/master/springboot-springplugin-strategy