Spring策略模式之Spring Plugin

  • 一般來說,簡單的策略模式大概有這麼2種用法,分別是:

    1. 傳入一個參數作爲策略,然後根據參數做一些事情,比如TreeMapComparator接口
    2. 傳入一個參數作爲策略,然後根據參數返回一個對應的對象,然後用戶拿到此對象做一些事情
  • 我們在使用Spring時往往是使用如下方式:

    • 定義一個接口Stratege

      public interface Stratege {
          void doSomething(String param);
      }
      
    • 定義2個實現類AB

      @Component
      public static class A implements Stratege {
          @Override
          public void doSomething(String param) {
              // ...
          }
      }
      
      @Component
      public static class B implements Stratege {
          @Override
          public void doSomething(String param) {
              // ...
          }
      }
      
    • 於是就可以在某個注入類似Map<String, Stratege>或者List<Stratege>對象,然後從集合中獲取相應的對象

  • 上述方式是可以很好的運行的,以前也一直這麼用,某天看Swagger源碼的時候發現Swagger用了很多Plugin方式,於是研究了一下Spring的plugin

  • 官網上說,這是有史以來最小的插件,數了下,整個包只有十來個類,他的原理和上面方式是一樣的,也是通過傳入某個參數,然後返回一個對象的對象,只不過上面的Map變成了PluginRegistry對象,Mapget(k)方法變成了getPluginFor或者getRequiredPluginFor(接口還有一些其他的方法,都是類似的)

    • 定義接口參數對象

      public class Param {
          String key;
      }
      
    • 定義接口

      public interface Stratege extends Plugin<Param> {
          void doSomething(Param param);
      }
      
    • 定義2個實現類AB

      @Component
      public class A implements Stratege {
          @Override
          public void doSomething(Param param) {
        	  // ...
          }
      
          @Override
          public boolean supports(Param delimiter) {
        	  return delimiter.key.equals("a");
          }
      }
      
      @Component
      public class B implements Stratege {
          @Override
          public void doSomething(Param param) {
        	  // ...
          }
      
          @Override
          public boolean supports(Param delimiter) {
        	  return delimiter.key.equals("b");
          }
      }
      
    • 在Spring啓動類頭頂增加註解:

      @SpringBootApplication
      @EnablePluginRegistries({Stratege.class})
      public class Application {}
      
    • 於是就可以注入策略對象:

      @RestController
      @RequestMapping("/stratege")
      public class StrategeController {
          @Resource
          private PluginRegistry<Stratege, Param> registry;
      
          @PostMapping("/doSomething")
          public void doStratege(@RequestBody Param param) {
        	  Stratege stratege = registry.getRequiredPluginFor(param);
        	  stratege.doSomething(param);
          }
      }
      
  • 關於插件的運行機制,也是比較簡單,Spring的@EnableXXX的原理都是類似的,通過註解,啓動Spring時解析註解,注入的容器

  • 總結:Map方式一般是通過對象名來獲取bean,插件通過boolean supports(S delimiter)方法作爲條件,插件方式靈活一點,但是這個插件由於比較小衆,用的人少

    發表評論
    所有評論
    還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
    相關文章