Spring策略模式之Spring Plugin
-
一般来说,简单的策略模式大概有这么2种用法,分别是:
- 传入一个参数作为策略,然后根据参数做一些事情,比如
TreeMap
的Comparator
接口 - 传入一个参数作为策略,然后根据参数返回一个对应的对象,然后用户拿到此对象做一些事情
- 传入一个参数作为策略,然后根据参数做一些事情,比如
-
我们在使用
Spring
时往往是使用如下方式:-
定义一个接口
Stratege
public interface Stratege { void doSomething(String param); }
-
定义2个实现类
A
和B
:@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
对象,Map
的get(k)
方法变成了getPluginFor
或者getRequiredPluginFor
(接口还有一些其他的方法,都是类似的)-
定义接口
参数对象
public class Param { String key; }
-
定义接口
public interface Stratege extends Plugin<Param> { void doSomething(Param param); }
-
定义2个实现类
A
和B
:@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)
方法作为条件,插件方式灵活一点,但是这个插件由于比较小众,用的人少