Java 将参数传递给@Inject Bean 的实例

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/22994716/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 19:52:16  来源:igfitidea点击:

Pass Parameter to Instance of @Inject Bean

javacdi

提问by Joe Almore

I am using CDI as injection framework, but I have found some limitations in its usage, and this is one of them. I am trying to initialize the creation of a bean instance with runtimevalues. Example:

我使用 CDI 作为注入框架,但我发现它的使用有一些限制,这就是其中之一。我正在尝试使用运行时值初始化 bean 实例的创建。例子:

@RequestScoped
public class MyNumber {
   int number;

   public MyNumber(int number) {
      this.number = number;
   }

   public String toString() {
      return "Your number is: " + number;
   }
}

public class UseNumber {
   @Inject
   Instance<MyNumber> number;

   public void doStuff() {
      int a = 8;
      MyNumber mN = number.select(a).get(); // ?? - Obviously this does not work.

      System.out.print(mN); // Should print: "Your number is: 8"
   }
}

Please, notice that "a" is a constant in the example, but in practice it is a variable; I clarify this so you don't post an answer with a @Producerto inject the value then in the constructor of MyNumber.

请注意,“a”在示例中是一个常量,但实际上它是一个变量;我澄清了这一点,所以你不要发布一个答案,@Producer然后在MyNumber.

Now, anybody has an idea about how can I do that?

现在,有人知道我该怎么做吗?

回答by Matej Bri?kár

According to the specification, there is no way to have a bean with a not simple, "not injecting" constructor (3.1. Managed beans , 3.9. Bean constructors ).

根据规范,没有办法让 bean 具有不简单的“非注入”构造函数(3.1. Managed beans3.9. Bean constructors)。

Therefore, the ways to set the parameters are to have the setMethod() for them, make them as @Inject fields in the bean or annotate the constructor with the annotation @Inject and make the parameters of the constructor to be injectable (5.5.1. Injection using the bean constructor )

因此,设置参数的方法是给它们设置setMethod(),将它们作为bean中的@Inject字段,或者用@Inject注解对构造函数进行注解,并使构造函数的参数成为可注入的( 5.5.1 . 使用 bean 构造函数注入)

I hope, I answered the question.

我希望,我回答了这个问题。

回答by Antoine Sabot-Durand

I'm not sure what you're trying to do, but from what I understand you want to initialize your bean with data in injection point annotation or at runtime thru programmatic lookup. You can do this by using InjectionPointmeta data in your bean (the only constraint will be to put your bean in dependent scope)

我不确定您要做什么,但据我所知,您想使用注入点注释中的数据或在运行时通过程序查找来初始化 bean。你可以通过InjectionPoint在你的 bean 中使用元数据来做到这一点(唯一的限制是将你的 bean 放在依赖范围内)

You can do something like this.

你可以做这样的事情。

First create a qualifier with a non binding value.

首先创建一个具有非绑定值的限定符。

@Qualifier
@Target({TYPE, METHOD, PARAMETER, FIELD})
@Retention(RUNTIME)
@Documented
public @interface Initialized {

    @Nonbinding int value() default 0; // int value will be store here 
}

You have to add this qualifier on your bean and analyze InjectionPointat creation time.

您必须在 bean 上添加此限定符并InjectionPoint在创建时进行分析。

@Initialized
public class MyNumber {
   int number;

   private int extractValue(InjectionPoint ip) {
    for (Annotation annotation : ip.getQualifiers()) {
        if (annotation.annotationType().equals(Initialized.class))
            return ((Initialized) annotation).value();
    }
    throw new IllegalStateException("No @Initialized on InjectionPoint");
  }

   @Inject
   public MyNumber(InjectionPoint ip) {
      this.number = extractValue(ip);
   }

   public String toString() {
      return "Your number is: " + number;
   }
}

You can now inject an initialized number like this:

您现在可以像这样注入一个初始化的数字:

@Inject
@Initialized(8)
MyNumber number;

If you want to decide the initialization value at runtime, you'll have to use programmatic lookup:

如果要在运行时决定初始化值,则必须使用程序化查找:

First create the annotation literal for `@Initialized``

首先为 `@Initialized` 创建注释文字

public class InitializedLiteral extends AnnotationLiteral<Initialized> implements Initialized {

    private int value;

    public InitializedLiteral(int value) {
        this.value = value;
    }

    @Override
    public int value() {
        return value;
    }
}

Then you can use Instanceto create your bean.

然后你可以用它Instance来创建你的 bean。

public class ConsumingBean {

    @Inject
    @Any
    Instance<MyNumber> myNumberInstance;

    public MyNumber getMyNumberBeanFor(int value) {
     return myNumberInstance.select(new InitializedLiteral(value)).get();
    }
    ...
}

Remember this works only if MyNumberis in dependent scope which makes sense because it's the only way to change initialization value at each injection.

请记住,这仅MyNumber在依赖范围内有效时才有意义,因为这是在每次注入时更改初始化值的唯一方法。