的Spring bean工厂使用类名称
问题描述:
我有一个接口/实现像这样:的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);
这是去了解这个问题的最好方法是什么?有更好的做法吗?
答
你可以注入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
您可以按类从应用程序上下文中获取bean。但我怀疑这是否是一个合理的设计。我宁愿在'Message'中引入某种类型的消息类型标识符,并设置一个由MessageReceiver使用的messageType-vs-Processor查找映射图。 –
@Richard你几乎在那里应用程序上下文本身就是一个工厂接口来获得适当的基于类型或名称的bean。所以不要再定义一个工厂,而是编写一个实用类来获取基于类型或名称的bean。 – Barath