Программный поиск всех бинов параметризованного интерфейса

Учитывая тип:

public interface Foo<T, X extends A>{...}

Мне нужно использовать программный поиск, чтобы найти bean-компонент, который реализует данный интерфейс независимо от типов параметров. Из-за безопасного разрешения типов это возвращает пустой набор:

final Set<Bean<?>> foos= BeanManagerProvider.getInstance().getBeanManager().getBeans(Foo.class, new AnyLit());

или через Deltaspike:

org.apache.deltaspike.core.api.provider.BeanProvider.getDependent(Foo.class, new AnyLit())

где AnyLit:

private static class AnyLit extends AnnotationLiteral<Any> implements Any
{

}

Есть ли способ обойти это?

Спасибо


person Gee2113    schedule 21.06.2017    source источник


Ответы (2)


Я думаю, вы могли бы использовать TypeLiteral - специальный класс CDI, который может содержать тип и его параметры. Через это вы можете указать, что именно вы хотите примерно таким образом:

TypeLiteral<Foo<Object, Object>> typeLiteral = new TypeLiteral<Foo<Object, Object>>() {};
BeanManager bm; //assuming you can retrieve BM somehow
bm.getBeans(typeLiteral.getType(), new AnyLit());

Теперь это (я надеюсь) соответствует правилам назначения CDI (ВНИМАНИЕ: дженерики впереди, выпейте кофе, прежде чем читать). Короче говоря, вы хотите использовать Object как тип, чтобы:

  • Он находит все другие типы, такие как бар <Bar> (все они могут быть назначены Object)
  • Параметры, такие как FooImpl<T> implements Foo<T>, также можно назначать для Object.
  • Он также находит бобы необработанного типа, такие как MyFoo implements Foo
person Siliarus    schedule 21.06.2017
comment
Я взял вашу идею здесь и заставил ее работать для моего варианта использования - хотя это немного уродливо, но работает, как и ожидалось. Спасибо - person Gee2113; 22.06.2017
comment
Пожалуйста. Кстати, это не совсем уродливо - я имею в виду, что нет другого пути, кроме как иметь дополнительный класс, который содержит параметр типа. На самом деле это не ограничение CDI, а скорее ограничение Java. Из-за стирания типа вы теряете эту информацию, поэтому вам нужно восполнить ее в другом месте. - person Siliarus; 22.06.2017

Посмотрите на bean-компонент Instance, который предоставляется контейнером, и сделайте что-то вроде:

@Any
@Inject
private Instance<MyInterface<?>> myParametrizedInterfaces;

Компонент Instance является компонентом Iterable, что означает, что вы можете перебирать все компоненты, реализующие указанный интерфейс.

Обратите внимание на универсальный параметр ?. В этом случае все универсальные параметры будут совпадать (дженерики java)

person maress    schedule 21.06.2017
comment
Экземпляр работает нормально, однако в моем случае мне нужно искать bean-компоненты статически. Я в основном обертываю deltaspike DependentProvider (или аналогичный подход к получению зависимых bean-компонентов), чтобы он автоматически удалял зависимые bean-компоненты с областью действия после использования, чтобы предотвратить утечку памяти при вызове bean-компонентов с областью действия приложения. Спасибо, хотя ваш ответ будет полезен для некоторых - person Gee2113; 22.06.2017