Являются ли функции особенными в CDI по сравнению с @Inject и BeanManager.getBeans(Function.class)?

У меня есть два класса, которые я хочу ввести:

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

а также

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

Когда я пытаюсь использовать их в другом месте, я получаю другое поведение:

    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));

мой вывод:

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

что на одну строчку меньше, чем я ожидаю.

Может ли кто-нибудь объяснить, что здесь происходит?

Решение, спасибо Siliarus за то, что он направил меня по правильному пути:

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;
        }
    });

1 ответ

Решение

Если я получу ваш образец правильно, то вам не хватает первой строки - вывод из Function когда получено через BeanManager,

Я думаю, что Set<Bean<?>> functions пустой. Причиной тому являются дженерики. Function это общий тип и методы на BeanManager не очень хорошо с этим. Спецификация CDI довольно точно определяет разрешение Typesafe для параметризованных типов(хотя и требует некоторого чтения).

Короче говоря, ваш боб типаFunction<String, String>не может быть назначен только сырой Function.class, который вы передаетеBeanManagerметод.

В качестве примечания: если вы хотите создавать экземпляры параметризованных типов на лету, вы всегда можете использоватьInstance<T>, который поддерживает использованиеTypeLiteral - специальная конструкция, которая содержит не только необработанный тип, но и информацию о фактических параметрах.

Другие вопросы по тегам