在開發中我們會經常看到,一個接口被多個實現類繼承。那么我們實際開發中如何解決,分配路由多個實現類的、
首先說一下用到的技術也很簡單。那就是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名稱去找對應的接口實現。,然后用接口返回接收。