Spring Boot中一接口多实现

一般常规场景是一接口一个实现实例 , 就像这样子
public interface ISayService {String say();}@Servicepublic class SayServiceImpl implements ISayService {@Overridepublic String say() {return "帅哥/美女 , 你们长得真好看";}}然后直接通过Autowired来获取实例
@Api(value = "http://kandian.youth.cn/index/Demo", tags = {"Demo"})@RestController@RequestMapping("query")public class DemoController {@AutowiredISayService sayService;@ApiOperation(value = "http://kandian.youth.cn/index/查询信息", notes = "查询信息")@PostMapping("info")public ResponseEntity queryInfo() {return ResponseEntity.ok(sayService.say());}}现在我们要做一个类似网关的鉴权功能 , 所有要调外部接口的的应用都调我们的接口 , 接口调用者只需要传入约定好的标识和参数即可得到相应接口的结果 , 服务端根据参数去判断是调用的哪个接口 , 因为不同厂商的接口逻辑和鉴权不一样 , 所以 , 有时候就要根据不同的厂商去实现一套逻辑 , 那么在程序调用的时候 , 就会涉及到多个实例 , 根据调用者参数去获取不同的实例并执行 。
上面的例子是 , 不管男女 , 我都说:"长得真好看" , 但是我可能 , 对女生说:"美女 , 你好漂亮啊" , 对男生说:"帅哥 , 你真是超帅" 。 其实 , Spring也给我们提供好几种方式 , 这里 , 我就把我知道的几种记录下来吧 。
@Service("sayService")public class SayServiceImpl implements ISayService {@Overridepublic String say() {return "帅哥/美女 , 你们长得真好看";}}@Service("girlService")public class GirlServiceImpl implements ISayService {@Overridepublic String say() {return "美女 , 你好漂亮啊";}}@Service("boyService")public class BoyServiceImpl implements ISayService {@Overridepublic String say() {return "帅哥 , 你真是超帅";}}【Spring Boot中一接口多实现】注意 , 多个实例 , 一定要在Service注解中加入对应的标识 , 不然会报错哟 ,
Spring Boot中一接口多实现文章插图
好了 , 实现类都弄好了 , 那么来看看怎么调用呢?这里有我们知道的有三种 , 第一种就是通过变量名 , 就像这样子
@AutowiredISayService sayService;@AutowiredISayService girlService;@AutowiredISayService boyService;它会通过变量命名去取出注入到容器中的实例类 , 第二种就是通过Qualifler ,
@Autowired@Qualifier("sayService")ISayService service1;@Autowired@Qualifier("girlService")ISayService service2;@Autowired@Qualifier("boyService")ISayService service3;
Spring Boot中一接口多实现文章插图
前面两种都是比较固定的 , 在我现在这个功能中是不合适的 , 所以 , 就需要第三种了 , 通过ApplicationContextAware来获取实例 , 这里我们先新建一个类来继承ApplicationContextAware类
@Componentpublic class ApplicationContextHandler implements ApplicationContextAware {private static ApplicationContext applicationContext;@Overridepublic void setApplicationContext(ApplicationContext applicationContext) throws BeansException {this.applicationContext = applicationContext;}public static Object getBean(String beanName) {return applicationContext.getBean(beanName);}}这里我们直接通过名字去获取实例
@Api(value = "http://kandian.youth.cn/index/Demo", tags = {"Demo"})@RestController@RequestMapping("query")public class DemoController {@ApiOperation(value = "http://kandian.youth.cn/index/查询信息", notes = "查询信息")@PostMapping("info")public ResponseEntity queryInfo(String beanName) {ISayService sayService=(ISayService) ApplicationContextHandler.getBean(beanName);return ResponseEntity.ok(sayService.say());}}好 , 现在我们传入不同的beanName来动态获取实例并执行,我们来看看效果
Spring Boot中一接口多实现文章插图
Spring Boot中一接口多实现文章插图
这里 , 把我们同事写的SpringUtils类粘贴出来 , 当然 , 我也不知道他是在哪里的复制粘贴的
@Componentpublic class SpringUtils implements ApplicationContextAware {private static ApplicationContext APPLICATION_CONTEXT = null;private SpringUtils() {}@Overridepublic void setApplicationContext(ApplicationContext applicationContext) throws BeansException {if (SpringUtils.APPLICATION_CONTEXT == null) {SpringUtils.APPLICATION_CONTEXT = applicationContext;}}/*** 获取ApplicationContext** @return*/public static ApplicationContext getApplicationContext() {return APPLICATION_CONTEXT;}/*** 通过name获取 Bean.** @param name* @return*/public static Object getBean(String name) {return getApplicationContext().getBean(name);}/*** 通过class获取Bean.** @param clazz* @param* @return*/public staticT getBean(Class clazz) {return getApplicationContext().getBean(clazz);}/*** 通过name,以及Clazz返回指定的Bean** @param name* @param clazz* @param* @return*/public staticT getBean(String name, Class clazz) {return getApplicationContext().getBean(name, clazz);}}