最近公司项目有个代码设计需求:需要在RiskControlTaskController 中调用RiskControlService ,而RiskControlService 有多个实现类,如何在程序运行的过程中,动态的区调用接口的某个具体的实现类?
业务场景的参考代码如下:
接口实现类一:
@Transactional
@Service("hnRiskControlServiceImpl")
public class HnRiskControlServiceImpl implements RiskControlService
接口实现类二:
@Transactional
@Service("zjRiskControlServiceImpl")
public class ZjRiskControlServiceImpl implements RiskControlService
controller:
@RestController
@RequestMapping("/***/*****")
public class RiskControlTaskController {
private RiskControlService riskControlService;
@RequestMapping("/****")
public Response sendDataToTaskCenter(@RequestBody ParamDto paramDto) {
tasks = riskControlService.verifyTasks(paramDto);
}
可能细心的人会注意到 : private RiskControlService riskControlService; 此处我并没有使用
@Autowired +@Qualifier,@Resource(name = "") 等等注解,当然使用@Conditional()注解可以解决唯一条件注入的问题。注意:不要有在程序运行的过程中为@Resource修改name属性值,以此来达到动态注入的想法,因为在默认情况下,spring注入的bean是单例的。
引出ApplicationContextAware
为什么类只要实现了ApplicationContextAware 就可以从spring中获取ioc容器
因为,有一个类,叫ApplicationContextAwareProcessor 实现了BeanPostProcessor(Bean的后置处理器) 重写了postProcessBeforeInitialization()方法----会在ioc容器中的bean初始化之前执行。在该方法内部,只要是ApplicationContextAware 的子类,就将bean强转为ApplicationContextAware 调用 setApplicationContext方法 ,设置applicationContext;
由此参照ApplicationContextAware 贴出我的解决方案:
首先:
public interface RiskControlTaskControllerAware extends Aware {
void setRiskControlService(RiskControlService riskControlService) throws BeansException;
}
然后:
@Configuration
public class SendTaskServiceAware implements BeanPostProcessor {
//1-浙江,2-湖南
@Value("${deploymentLocation}")
private Integer disposePlace;
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
invokeAwareInterfaces(bean);
return bean;
}
private void invokeAwareInterfaces(Object bean) {
if (bean instanceof RiskControlTaskControllerAware) {
HnRiskControlServiceImpl hnRiskControlServiceImpl = (HnRiskControlServiceImpl) SpringBeanUtil.getBeanFromSpringByBeanName("hnRiskControlServiceImpl");
ZjRiskControlServiceImpl zjRiskControlServiceImpl = (ZjRiskControlServiceImpl) SpringBeanUtil.getBeanFromSpringByBeanName("zjRiskControlServiceImpl");
if (1 == disposePlace) {
((RiskControlTaskControllerAware) bean).setRiskControlService(zjRiskControlServiceImpl);
} else if (2 == disposePlace) {
}
((RiskControlTaskControllerAware) bean).setRiskControlService(hnRiskControlServiceImpl);
}
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
}
最后:
public class RiskControlTaskController implements RiskControlTaskControllerAware {
private RiskControlService riskControlService;
@Override
public void setRiskControlService(RiskControlService riskControlService) throws BeansException {
this.riskControlService = riskControlService;
}
}