Pass Parameter to Instance of @Inject Bean

后端 未结 2 568
天涯浪人
天涯浪人 2020-12-30 06:38

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 wit

2条回答
  •  滥情空心
    2020-12-30 07:03

    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 InjectionPoint meta data in your bean (the only constraint will be to put your bean in dependent scope)

    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 InjectionPoint at creation time.

    @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``

    public class InitializedLiteral extends AnnotationLiteral implements Initialized {
    
        private int value;
    
        public InitializedLiteral(int value) {
            this.value = value;
        }
    
        @Override
        public int value() {
            return value;
        }
    }
    

    Then you can use Instance to create your bean.

    public class ConsumingBean {
    
        @Inject
        @Any
        Instance myNumberInstance;
    
        public MyNumber getMyNumberBeanFor(int value) {
         return myNumberInstance.select(new InitializedLiteral(value)).get();
        }
        ...
    }
    

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

提交回复
热议问题