结合@Produce和@Qualifier的动态对象创建

时间:2013-01-21 13:36:29

标签: java-ee glassfish cdi

我必须实现一个实例工厂,它返回一个新的消息处理程序实例,取决于消息代码。

有一个接口MessageHandler和这个接口的大约50个实现。由于项目结构(maven循环依赖...),工厂类与具体接口实现没有依赖关系。

messageHandler接口:

interface MessageHandler {
    void receive(Message message);

    MessageCode getMessageCode();
}

每个MessageHandler实现都返回一个唯一的消息代码。 例如:

class FirstMessageHandler implements MessageHandler {
     ...
     @Override
     MessageCode getMessageCode(){
          return MessageCodes.MESSAGE_TYPE_ONE;
     }
     ...
}

class SecondMessageHandler implements MessageHandler {
     ...
     @Override
     MessageCode getMessageCode(){
          return MessageCodes.MESSAGE_TYPE_TWO;
     }
     ...
}

MessageHandlerFactory应为每条消息创建新的处理程序实例。 工厂没有关于具体实现的信息,也没有依赖关系 到实现的maven包。它只有messageCodes。

class MessagehandlerFactory {
       MessageHandler createHandler(MessageCode messageCode){
       ...
       }
}

在搜索之后,我找到了一个关于@Produce注释的例子,这个很好的例子:

http://docs.oracle.com/javaee/6/tutorial/doc/gkgkv.html

但是在这个例子中,我需要知道工厂中的所有实现类型,这是不允许的。

实际上解决方案是使用@Any @Instance。

 @Inject
 @Any
 private Instance<MessageHandler> messageHandlers;

@PostConstruct
public void init() {
    for (MessageHandler handler : messageHandlers) {
        messageHandlerMap.put(handler.getMessageCodes(), handler);
    }
}

但是此代码为每个收到的消息的所有MessageHandler实现的每个消息实例创建。 可以组合@Produce和@Qualifier,以便根据收到的MessageCode只创建一个MessageHandler实例吗?

我正在使用Glassfish 3.1.2.2。

2 个答案:

答案 0 :(得分:2)

您可以通过观察ProcessAnnotatedType获取便携式扩展中的所有实例。将这些存储在侦听器类中的另一个类或静态集合中,然后您可以通过注入类来获取所有这些实例。

另一个选项是将InjectionPoint注入到您的producer方法中,并使用其中的信息返回Instance遍历期间所需的实例。但请注意,这仅适用于依赖范围的注入。

答案 1 :(得分:0)

不确定我理解您的功能要求。

听起来像生产者模式是错误的选择,如果你不知道要生产什么,那么为什么选择呢?

我不遵循代码实际执行的操作,但是让我问一下,如果只是拥有接口并进行实现会有什么问题?

每个新实现都获得它自己的限定符,任何上下文实例都可以使用@Inject @QualifierName来获取它。

我实际上认为你可能会无缘无故地做复杂的事情,但我不确定,因为我真的不明白这个问题: - )