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