spring如何實現一個接口多個實現類的自動分配


    在開發中我們會經常看到,一個接口被多個實現類繼承。那么我們實際開發中如何解決,分配路由多個實現類的、

 

    首先說一下用到的技術也很簡單。那就是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名稱去找對應的接口實現。,然后用接口返回接收。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 
       


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM