如何使用CDI进行方法参数注入?

kos*_*tja 19 java dependency-injection cdi jboss-weld

是否可以使用CDI将参数注入方法调用?预期的行为类似于现场注入.查找首选生产者并使用产品.

我想做的是:

public void foo(@Inject Bar bar){
  //do stuff
} 
Run Code Online (Sandbox Code Playgroud)

或者这个(使用较少混淆的sytax):

public void foo(){
  @Inject 
  Bar bar;
  //do stuff
} 
Run Code Online (Sandbox Code Playgroud)

在这两种情况下,此语法都是非法的 还有其他选择吗?如果不是 - 如果有可能,出于某种原因,这会是一个坏主意吗?

谢谢

编辑 - 我可能已经使我的要求不够清楚 - 我希望能够直接调用该方法,将bar变量的初始化留给容器.JörnHorstmann和Perception的回答表明这是不可能的.

Per*_*ion 19

当bean被容器实例化时,将为bean处理注入点,这限制了方法级注入的用例数.规范的当前版本识别以下类型的方法注入:

初始化方法注入

public class MyBean {
    private Processor processor;

    @Inject
    public void setProcessor(final Processor processor) {
        this.processor = processor;
    }
}
Run Code Online (Sandbox Code Playgroud)

MyBean注入一个实例时,处理器实例也将通过它的setter方法注入.

事件观察者方法

public class MyEventHandler {
    public void processSomeEvent(@Observes final SomeEvent event) {
    }
}
Run Code Online (Sandbox Code Playgroud)

事件实例直接注入到事件处理方法中(但不是使用@Inject注释)

制片人方法

public class ProcessorFactory {
    @Produces public Processor getProcessor(@Inject final Gateway gateway) {
        // ...
    }
}
Run Code Online (Sandbox Code Playgroud)

生成器方法的参数自动注入.


Bin*_*Ren 9

如果您真正想要的不是作为方法的参数(应该由调用者提供),而是每次调用方法并完全构造和注入时正确初始化CDI bean的实例,然后检查

javax.inject.Provider<T>

基本上,首先向该类注入提供者

@Inject Provider<YourBean> yourBeanProvider;
Run Code Online (Sandbox Code Playgroud)

然后,在该方法中,获取一个新实例

YourBean bean = yourBeanProvider.get();
Run Code Online (Sandbox Code Playgroud)

希望这可以帮助 :)


dcs*_*ohl 8

当我最初对这个主题进行搜索时出现了这个问题,并且我已经了解到随着CDI 1.1的发布(包含在JavaEE 7规范中),现在有一种方法可以实际执行OP所需的部分内容.你还是做不到

public void foo(@Inject Bar bar){
   //do stuff
}
Run Code Online (Sandbox Code Playgroud)

但你可以"注入"一个局部变量,虽然你不使用@Inject,而是以编程方式查找注入的实例,如下所示:

public void foo() {
    Instance<Bar> instance = CDI.current().select(Bar.class);
    Bar bar = instance.get();
    CDI.current().destroy(instance);
    // do stuff with bar here
}
Run Code Online (Sandbox Code Playgroud)

请注意,该select()方法可选择使用您可能需要提供的任何限定符注释.祝你好运获得实例java.lang.annotation.Annotation.迭代你可以更容易Instance<Bar>找到你想要的那个.

我被告知你需要Instance<Bar>像我上面所做的那样销毁它,并且可以从经验中验证上述代码的工作原理; 但是,我不能发誓你需要摧毁它.


Jör*_*ann 5

CDI的这一特性称为"初始化方法".语法与您的代码的不同之处在于整个方法都带有注释@Inject,方法参数可以通过限定符进一步注释以选择特定的bean.JSR 299的 3.9节显示了以下示例,@Selected如果只有一个bean实现,则可以省略限定符.

@Inject
void setProduct(@Selected Product product) {
    this.product = product;
}
Run Code Online (Sandbox Code Playgroud)

请注意

应用程序可以直接调用初始化方法,但是容器不会将任何参数传递给方法.