2017-09-04 4 views
0

J'ai deux classes, que je souhaite injecter:Sont des fonctions spéciales dans CDI w.r.t. @Inject vs BeanManager.getBeans (Function.class)?

@ApplicationScoped 
public class BeanThing { 
    public String apply(String s) { 
     return "bt(" + s + ")"; 
    } 
} 

et

@ApplicationScoped 
public class ClassFunction implements Function<String, String> { 
    @Override 
    public String apply(String s) { 
     return "cf(" + s + ")"; 
    } 
} 

Lorsque je tente de les utiliser ailleurs je reçois un comportement différent:

Set<Bean<?>> functions = beanManager.getBeans(Function.class); 
    for (Bean<?> untyped : functions) { 
     Bean<Function<String, String>> typed = (Bean<Function<String, String>>) untyped; 
     Function<String, String> function = beanManager.getContext(typed.getScope()).get(typed, beanManager.createCreationalContext(typed)); 
     System.err.println(function.apply("beanManager")); 
    } 

    Set<Bean<?>> beanThings = beanManager.getBeans(BeanThing.class); 
    for (Bean<?> untyped : beanThings) { 
     Bean<BeanThing> typed = (Bean<BeanThing>) untyped; 
     BeanThing beanThing = beanManager.getContext(typed.getScope()).get(typed, beanManager.createCreationalContext(typed)); 
     System.err.println(beanThing.apply("beanManager")); 
    } 

    System.err.println(injectedFunction.apply("injected")); 
    System.err.println(beanThing.apply("injected")); 
    System.err.println("injectedFunction is a function: " + (injectedFunction instanceof Function)); 

ma sortie est :

bt(beanManager) 
cf(injected) 
bt(injected) 
injectedFunction is a function: true 

qui est une ligne de moins que ce à quoi je m'attends.

Quelqu'un pourrait-il nous expliquer ce qui se passe ici?

Solution, grâce à Siliarus pour me mettre hors sur le droit chemin:

Set<Bean<?>> functions = beanManager.getBeans(new ParameterizedType() { 

     @Override 
     public Type[] getActualTypeArguments() { 
      return new Type[]{new WildcardType() {...}, new WildcardType() {...}; 
     } 

     @Override 
     public Type getRawType() { 
      return Function.class; 
     } 
    }); 

Répondre

0

Si je reçois votre échantillon correctement ce qui vous manque est la première ligne - sortie du Function lorsqu'il est obtenu par BeanManager. Je pense que le Set<Bean<?>> functions est vide. La raison en est génériques. Function est un type générique et les méthodes sur BeanManager ne sont pas vraiment bonnes avec ça. CDI spec définit assez bien (bien qu'il prenne un peu de lecture) Typesafe resolution for parameterized types.

En résumé, votre bean de type Function<String, String> ne peut pas être affecté à la méthode Function.class, que vous passez à la méthode BeanManager. En guise de remarque, si vous souhaitez instancier des types paramétrés à la volée, vous pouvez toujours utiliser Instance<T>, qui prend en charge l'utilisation de TypeLiteral - une construction spéciale qui contient non seulement le type brut, mais aussi des informations sur les paramètres réels.

+0

Merci pour la réponse. Je demande au BeanManager parce que je veux savoir sur les autres Qualifiers sur le haricot, comme je suis sûr que vous avez deviné étant donné les types impliqués cela sera finalement un producteur retournant un lambda plutôt qu'une classe dédiée. Je ne sais toujours pas comment demander le gestionnaire de bean pour la fonction ? –

+0

Donc, en donnant au BM quelques informations de type utiles, ça allait. Je devais juste être très explicite, ParametrizedType, avec deux WildcardTypes comme argumentTypes. –

+0

Heureux que vous l'ayez compris! :) – Siliarus