一般常規場景是一接口一個實現實例,就像這樣子
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);
}
}
今天就先到這里吧,大叔準備下班回家了。雖然年紀大了,但是還是每天學習一點,每天進步一點。如果有哪里寫得不對的,還請各位小友指正,只有不斷試錯,才能慢慢提高。如果你覺得對你有幫助,請點贊+關注,謝謝!!!!!!