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注解中加入对应的标识 , 不然会报错哟 ,
文章插图
好了 , 实现类都弄好了 , 那么来看看怎么调用呢?这里有我们知道的有三种 , 第一种就是通过变量名 , 就像这样子
@AutowiredISayService sayService;@AutowiredISayService girlService;@AutowiredISayService boyService;
它会通过变量命名去取出注入到容器中的实例类 , 第二种就是通过Qualifler ,
@Autowired@Qualifier("sayService")ISayService service1;@Autowired@Qualifier("girlService")ISayService service2;@Autowired@Qualifier("boyService")ISayService service3;
文章插图
前面两种都是比较固定的 , 在我现在这个功能中是不合适的 , 所以 , 就需要第三种了 , 通过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来动态获取实例并执行,我们来看看效果
文章插图
文章插图
这里 , 把我们同事写的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);}}
- 空调|让格力、海尔都担忧,中国取暖“新潮物”强势来袭,空调将成闲置品?
- 国外|坐拥77件专利,打破国外的垄断,造出中国最先进的家电芯片
- 手机基带|为了5G降低4G网速?中国移动回应来了:罪魁祸首不是运营商
- 通气会|12月4~6日,2020中国信息通信大会将在成都举行
- 中国|浅谈5G移动通信技术的前世和今生
- 操盘|中兴统一操盘中兴、努比亚、红魔三大品牌
- Blade|售价2798元 中兴Blade 20 Pro 5G手机发布 骁龙765G配四摄
- 健身房|乐刻韩伟:产业互联网中只做单环节很难让数据发挥大作用
- 垫底|5G用户突破2亿:联通垫底,电信月增700万,中国移动有多少?
- 计费|5G是如何计费的?