多个接口注入
当一个interface接口中有多个实现类的时候,控制层该如何注入指定的实现类呢?
之前面试的时候碰到过这个问题,由于我从来没碰到过,之前工作写的基本也都是一个控制对一个接口对一个实现类
所以完全没考虑过这个事情,这周在写阿里云短信的发送接口的时候,就出现了这个问题,
由于我的短信实现类是通用的短信实现类,里面还要去执行不同供应商的实现类,然后不同短信供应商的实现类又都实现了interface接口
于是控制层注入的时候就出现了问题。
具体问题描述
经过百度以及查阅博客,总结了几种不同的办法,用于注入指定接口。
先看下我的几个类
控制层
/**
* @Author WuXinYu
* @Date 2021/3/2 13:36
* @Version 1.0
*/
@Controller
@RequestMapping("/messageSend")
public class SmsController {
@Autowired
private SmsService smsService;
/*
* 告警短信接口
* 入参为
* phoneNumbers 收信人手机号,多个的时候需要用逗号隔开
* deviceCode 异常设备编号
* */
@RequestMapping("/warn")
@ResponseBody
public ResponseBase warn(@RequestParam("phoneNumbers") String phoneNumbers, @RequestParam("deviceCode") String deviceCode){
ResponseBase result = smsService.sendWarnSms(phoneNumbers, deviceCode);
return result;
}
接口层
/**
* @Author WuXinYu
* @Date 2021/3/2 13:39
* @Version 1.0
*/
public interface SmsService {
ResponseBase sendWarnSms(String phoneNumbers, String templateParam);
ResponseBase sendRecoverSms(String phoneNumbers,String templateParam);
ResponseBase sendCommonSms(String phoneNumbers,String templateParam ,String signName,String templateCode);
}
实现类
/**
* @Author WuXinYu
* @Date 2021/3/3 10:55
* @Version 1.0
*/
@Service
public class SmsServiceImpl implements SmsService {
@Autowired
private AliSmsService aliSmsService;
@Autowired
private XSmsService xSmsService;
private Map<String, SmsService> smsSereviceMap = new HashMap<>();
}
因为我在短信的通用实现类中,注入了两个具体实现类,一个阿里供应商的短信实现类,和一个为止供应商的短信实现类(方便代码升级增加供应商)
所以这两个具体的实现类也实现了interface接口。
阿里实现类
@Service
public class AliSmsService implements SmsService{}
公共实现类
@Service
public class XSmsService implements SmsService{}
具体逻辑代码里面没有贴出来算是公司机密把哈哈哈
那么怎么解决呢
1.使用@Primary注解
在实现类上面加上@Primary注解,指明该类的优先级最高,注入的时候就会使用优先级高的实现类
@Service
@Primary
public class SmsServiceImpl implements SmsService {}
2.通过@Autowired和@Qualifier组合注解
使用这两个组合注解,可以在控制层注入接口的时候指明具体的实现方法。
@Autowired
@Qualifier(value = “smsServiceImpl”)
/**
* @Author WuXinYu
* @Date 2021/3/2 13:36
* @Version 1.0
*/
@Controller
@RequestMapping("/messageSend")
public class SmsController {
@Autowired
@Qualifier(value = "smsServiceImpl")
private SmsService smsService;
/*
* 告警短信接口
* 入参为
* phoneNumbers 收信人手机号,多个的时候需要用逗号隔开
* deviceCode 异常设备编号
* */
@RequestMapping("/warn")
@ResponseBody
public ResponseBase warn(@RequestParam("phoneNumbers") String phoneNumbers, @RequestParam("deviceCode") String deviceCode){
ResponseBase result = smsService.sendWarnSms(phoneNumbers, deviceCode);
return result;
}
}
3.使用@Resource注入
这个注解添加指定的默认名即可指定实现类
@Resource(name = “smsServiceImpl”)
/**
* @Author WuXinYu
* @Date 2021/3/2 13:36
* @Version 1.0
*/
@Controller
@RequestMapping("/messageSend")
public class SmsController {
@Resource(name = "smsServiceImpl")
private SmsService smsService;
/*
* 告警短信接口
* 入参为
* phoneNumbers 收信人手机号,多个的时候需要用逗号隔开
* deviceCode 异常设备编号
* */
@RequestMapping("/warn")
@ResponseBody
public ResponseBase warn(@RequestParam("phoneNumbers") String phoneNumbers, @RequestParam("deviceCode") String deviceCode){
ResponseBase result = smsService.sendWarnSms(phoneNumbers, deviceCode);
return result;
}
}
4.使用@Resource注入根据@Service注解添加的指定名称
在@Service注解中添加指定名称,可以使用@Resource注解指定这个名称从而指定实现类
@Service("sms")
public class SmsServiceImpl implements SmsService {
}
/**
* @Author WuXinYu
* @Date 2021/3/2 13:36
* @Version 1.0
*/
@Controller
@RequestMapping("/messageSend")
public class SmsController {
@Resource(name = "sms")
private SmsService smsService;
/*
* 告警短信接口
* 入参为
* phoneNumbers 收信人手机号,多个的时候需要用逗号隔开
* deviceCode 异常设备编号
* */
@RequestMapping("/warn")
@ResponseBody
public ResponseBase warn(@RequestParam("phoneNumbers") String phoneNumbers, @RequestParam("deviceCode") String deviceCode){
ResponseBase result = smsService.sendWarnSms(phoneNumbers, deviceCode);
return result;
}
}
总结
综合几种方法,本质都是差不多的,通过注解和指定实现类的name来指定具体的实现类。下次再碰到类似的情况就有经验了