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)方法作为条件,插件方式灵活一点,但是这个插件由于比较小众,用的人少

posted @ 2022-05-16 10:56  神一样的存在  阅读(1001)  评论(0编辑  收藏  举报