在开发中我们会经常看到,一个接口被多个实现类继承。那么我们实际开发中如何解决,分配路由多个实现类的、
首先说一下用到的技术也很简单。那就是spring的。ApplicationContext类、里面的getBeanofType();
直接代码:
首先定义一个个性接口
/** * 个性化定制服务接口 * @author david * */ public interface CustomPageTemplate extends PageTemplate { /** * 服务实现的优先级,数字越小越优先 */ public int priority(); /** * 服务实现能够处理的任务 */ public boolean accept(CrawlTask task); }
public interface PageTemplate {
/**
* 根据任务数据获取展示层模型
*/
Page getPageModel(CrawlTask task);
}
然后我们定义一个路由类,由这个类。选择不同的实现
@Component public class PageTemplateRouter { @Autowired private ApplicationContext applicationContext; private List<CustomPageTemplate> templates; public PageTemplateRouter() { // TODO Auto-generated constructor stub } @PostConstruct public void init(){ Map<String, CustomPageTemplate> beans = applicationContext.getBeansOfType(CustomPageTemplate.class); templates = beans.values().stream() .sorted((a,b)->a.priority()-b.priority()) .collect(Collectors.toList()); } /** * 根据任务情况判断应该选择具体的PageTemplate实现类 * @param task * @return */ public PageTemplate getPageTemplate(CrawlTask task){ return templates.stream().filter(t->t.accept(task)).findFirst().get(); } }
简单明了,一下,实现。但是这个可不是自动识别,下面我们就写一个,自动识别的
1.如何获取应用上下文对象,applicationcontext
任何类,实现 applicationContextAware接口,实现setApplicationContext方法,就会在启动时,向实现类的实现方法注入applicationcontext对象
@Component public class TestServiceFactory implements ApplicationContextAware { private static Map<TypeEnum, TestService> testServiceMap; @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { Map<String,TestService> map = applicationContext.getBeansOfType(TestService.class); testServiceMap = new HashMap<>(); map.forEach((key,value) -> testServiceMap.put(value.getCode(),value)); } public TestService getTestService(TypeEnum typeEnum) { return testServiceMap.get(typeEnum); } }
2. 怎么根据外部条件实现获得对应的实现类?
可以在接口中加一个getCode方法,实现类实现这个方法,然后返回一个定义的枚举类型,然后将getBeansOfType获得map进行转换
枚举:
package com.util; public enum TypeEnum { html, template }
接口:
package com.service; import com.util.TypeEnum; import org.springframework.stereotype.Service; @Service public interface TestService { public TypeEnum getCode(); public String test(); }
定义实现类:
@Service public class TestServiceHtml implements TestService { @Override public TypeEnum getCode() { return TypeEnum.html; } @Override public String test() { return this.toString(); } } @Service public class TestServiceTemplate implements TestService { @Override public TypeEnum getCode() { return TypeEnum.template; } @Override public String test() { return this.toString(); } }
controller类:
@Controller @RequestMapping("test") public class TestController { @Autowired TestServiceFactory testServiceFactory; private TestService testService; @ResponseBody @RequestMapping("test") public String test(HttpServletRequest request, HttpServletResponse response){ String type = request.getParameter("type"); testService = getTestService(type); return testService.test(); } public TestService getTestService(String type) { TypeEnum typeEnum = null; if(type.equals("1")) typeEnum = TypeEnum.html; if(type.equals("2")) typeEnum = TypeEnum.template; return testServiceFactory.getTestService(typeEnum); } }
以上两种模式都可以完成,多个实现类的自动分配。
这是其中一种,还有一种,一个接口,多个实现类。我们可以利用。applicationContext.getBean();这种实现方式。这也是spring获取实现类的方法。
例如:
applicationContext.getBean(task.identifier()+"/Provider", ProviderSao.class);
这样我们也可以根据,实现类上的id或者name名称去找对应的接口实现。,然后用接口返回接收。
原创文章,作者:奋斗,如若转载,请注明出处:https://blog.ytso.com/tech/pnotes/17121.html