2017-08-25 59 views
0

我有一個接口/實現像這樣:的Spring bean工廠使用類名稱

public interface Processor { 
    void processMessage(Message m); 
} 

@Component 
public class FooAProcessor implements Processor { 
    private FooA fooA; 

    public FooAProcessor(FooA fooA) { 
     this.fooA = fooA; 
    } 

    @Override 
    public void processMessage(Message m) { 
     //do stuff 
    } 
} 

@Component 
public class FooBProcessor implements Processor { 
    private FooA fooA; 

    public FooBProcessor(FooA fooA) { 
     this.fooA = fooA; 
    } 

    @Override 
    public void processMessage(Message m) { 
     //do stuff 
    } 
} 

FooA bean是簡單的,就像這樣:

@Component 
public class FooA { 
    //stuff 
} 

和消息類:

public class Message { 
    private Class clazz; 
} 

我正在將消息從隊列中拉出。我需要提供一個具體的處理器來適當地處理不同類型的消息。這裏的消息接收器:

public class MessageReceiver { 
    public void handleMessage(Message m) { 
     Processor processor = //get concrete implementation from Message clazz 
     processor.processMessage(m); 
    } 
} 

究竟如何,我可以使用類名/對象來定義一個具體實施Processor

我的第一個想法是開發某種類型的工廠,接受一個類並提供具體的實現。事情是這樣的:

@Component 
public class ProcessorFactory { 
    private FooAProcessor fooAProcessor; 
    private FooBProcessor fooBProcessor; 

    public ProcessorFactory(FooAProcessor fooAProcessor, FooBProcessor fooBProcessor) { 
     this.fooAProcessor = fooAProcessor; 
     this.fooBProcessor = fooBProcessor; 
    } 

    public Processor getFactory(Class clazz) { 
     if(clazz.isAssignableFrom(FooAProcessor.class)) { 
      return fooAProcessor; 
     } 
    } 
} 

還是要使用這樣的應用程序上下文:

AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(); 
ctx.getBean(clazz); 

這是去了解這個問題的最好方法是什麼?有更好的做法嗎?

+0

您可以按類從應用程序上下文中獲取bean。但我懷疑這是否是一個合理的設計。我寧願在'Message'中引入某種類型的消息類型標識符,並設置一個由MessageReceiver使用的messageType-vs-Processor查找映射圖。 –

+0

@Richard你幾乎在那裏應用程序上下文本身就是一個工廠接口來獲得適當的基於類型或名稱的bean。所以不要再定義一個工廠,而是編寫一個實用類來獲取基於類型或名稱的bean。 – Barath

回答

0

你可以注入ApplicationContext到您的工廠,並從那裏得豆:

@Component 
public class Factory { 

    @Autowired ApplicationContext applicationContext; 

    public Object getBean(String beanName) { 
     return applicationContext.getBean(beanName); 
    } 
} 

或者你可以把你的處理器集成到map並從它那裏得到他們:

@Component 
public class ProcessorFactory { 

    private final Processor fooAProcessor; 
    private final Processor fooBProcessor; 
    private final Map<Class<T extends Processor>, Processor> beanMap; 

    public ProcessorFactory (Processor fooAProcessor, Processor fooBProcessor) { 
     this.fooAProcessor = fooAProcessor; 
     this.fooBProcessor = fooBProcessor; 
     this.beanMap = new HashMap(2); 
    } 

    @PostConstruct 
    public void init() { 
     beanMap.put(FooAProcessor.class, fooAProcessor); 
     beanMap.put(FooBProcessor.class, fooBProcessor); 
    } 

    public Processor getProcessor(Class<T extends Processor> clazz) { 
     return beanMap.get(clazz); 
    } 
} 

我建議不要依賴在使用spring上下文時使用類名,而使用beanNames。

+0

我更喜歡你的第二個解決方案。我試過這樣做,但我不認爲你可以在Interface上做一個'extends'。我遇到了「意外的邊界」錯誤。 – Richard

相關問題