将运行时参数传递给包含Injections的Object

时间:2013-04-19 22:22:32

标签: java java-ee cdi

上下文

基于我的Java EE应用程序接收的XML,我想创建一个新的AreeConfiguration对象,其中发生3个对象的注入。选择正确的实例<>基于此XML中的信息发生。因此,我传递了这个XML的信息。

我有一个数据结构,应该在运行时填充这些AreeConfiguration对象:

private HashMap<Integer, AreeConfiguration> configurations = new HashMap<Integer, AreeConfiguration>();

public void parseNewConfiguration(Element el) throws InvalidDescriptorException {
    if(!isValidConfiguration(el)) throw new InvalidDescriptorException();

    int key = getUniqueKey();

    AreeConfiguration cfg = new AreeConfiguration(key, el);       
    configurations.put(key, cfg);
}

我的AreeConfiguration对象应该(理想情况下)使用基本的XML信息构造并注入一些对象。稍后,我想使用XML中的信息来选择正确的Instance&lt;&gt;。

public class AreeConfiguration {

@Inject
private Instance<AreeInput> ais;
private AreeInput ai;

@Inject
private Instance<AreeReasoner> ars;
private AreeReasoner ar;

@Inject
private Instance<AreeOutput> aos;
private AreeOutput ao;

AreeConfiguration(int key, Element el) throws InvalidDescriptorException {
    ...
}   

@PostConstruct
public void chooseComponents(){     
    ai = chooseInput();
    ar = chooseReasoner();
    ao = chooseOutput();
}

我找到并尝试过的内容:

通过研究(此处为Stack Overflow),我现在明白CDI不会在使用new Object()创建的对象中进行注入。上面显示的代码永远不会输入chooseComponents()

当我想尝试使用@Producer时,我使用parseNewConfiguration(Element el)注释@Producer并添加@New AreeConfiguration cfg参数。但是,我也无法传递Element el,这很不幸,因为它包含必要的XML信息。

如果我没有彻底解释自己,请提出其他问题。我正在寻找一种方法来使用CDI完成上述操作。

此外,在这个问题的答案中提出的解决方案是多么“干净”:@Inject only working for POJOs created by CDI container?

3 个答案:

答案 0 :(得分:1)

要对不是由CDI容器创建的实例执行注入,并且您可以访问BeanManager,那么您可以执行以下操作:

// Create a creational context from the BeanManager
CreationalContext creationalContext = beanManager.createCreationalContext(null);

// Create an injection target with the Type of the instance we need to inject into
InjectionTarget injectionTarget = beanManager.createInjectionTarget(beanManager.createAnnotatedType(instance.getClass()));

// Perform injection into the instance
injectionTarget.inject(instance, creationalContext);

// Call PostConstruct on instance
injectionTarget.postConstruct(instance);

可用于完成所有工作的类的示例位于:http://seamframework.org/Documentation/HowDoIDoNoncontextualInjectionForAThirdpartyFramework

答案 1 :(得分:1)

在这种特殊情况下,动态注入只需在客户致电后进行。因此,我现在只是在WebService中注入我需要的东西。当客户端调用WebService时,会自动执行注入。

@Path("newconfiguration")
@RequestScoped
public class NewConfigurationResource {

@Context
private UriInfo context;

@Inject
private AreeConfiguration injConfig;

public NewConfigurationResource() { }

@POST
@Path("post")
@Produces("application/json")
public Response postJson() {
    ...
    doSomething(injConfig);
    ...
} 

答案 2 :(得分:0)

您通常是正确的,最多可以将一些有限的数据类型传递给CDI来创建对象 - 即基本体,静态类型,字符串,枚举到您的限定符中。这是注释的限制。我对你的结构不太了解的一件事是客户将所有这些传递给你。这使您的代码更加脆弱,客户端和服务器更加紧密耦合。难道你不能传递一些代表某种配置的ID吗?您仍然存在无法传递XML元素的问题。你可以传递一个字符串,并在生产者方法的InjectionPoint中使用它。