Есть ли способ попросить Weld SE ввести конкретную реализацию в определенный момент времени?
Я использую Weld SE в приложении, в моем приложении у меня есть интерфейс, для которого у меня есть 3 реализации, но это вызывает неоднозначность для Weld. Насколько я вижу, техника разрешения неоднозначности в сварке статична, это можно сделать с помощью: @specialize, @alternative, @Named или с помощью Qualifier. но это мне не поможет Мне нужно уметь задавать реализацию класса данного интерфейса для каждого случая.
Я не мог найти решение для моего требования.
Вот код, который иллюстрирует мою точку зрения
public class Foo {
@Inject
MyInterface target;
public void doSomething() {
target.doIt();
}
}
public class Bar1 implements MyInterface {
public void doIt() {
System.out.println("Hello");
}
}
public class Bar2 implements MyInterface {
public void doIt() {
System.out.println("Goodbye");
}
}
public class FooMain {
public static void main(String[] args) {
Weld weld = new Weld();
final WeldContainer container = weld.initialize();
Foo foo1 = container.instance().select(Foo.class).get();
Foo foo2 = container.instance().select(Foo.class).get();
}
}
Этот код вызывает это исключение:
Exception in thread "main" org.jboss.weld.exceptions.DeploymentException: WELD-001409: Ambiguous dependencies for type MyInterface with qualifiers @Default
at injection point [BackedAnnotatedField] @Inject com.lodh.arte.test.cdi.Foo.target
at com.lodh.arte.test.cdi.Foo.target(Foo.java:0)
Possible dependencies:
- Managed Bean [class com.lodh.arte.test.cdi.Bar2] with qualifiers [@Any @Default],
- Managed Bean [class com.lodh.arte.test.cdi.Bar1] with qualifiers [@Any @Default]
Мне нужно динамически сообщить Weld, какую реализацию использовать для внедрения, как в этом воображаемом методе Weld.use:
Weld.use ( MyInterface.class, Bar1.class);
Foo foo1 = container.instance().select(Foo.class).get();
Weld.use ( MyInterface.class, Bar2.class);
Foo foo2 = container.instance().select(Foo.class).get();
Спасибо за помощь
С уважением
Надер
1 ответ
Сначала у вас есть две реализации MyInterface
, Bar1
а также Bar2
, Weld не знает, какую реализацию выбрать при впрыске MyInterface
, поэтому он выдает эту ошибку "Неоднозначные зависимости". Чтобы избежать этой ошибки, вы должны дать своей реализации разные квалификаторы.
Сначала вы должны квалифицировать свои реализации:
@MyQualifier1
public class Bar1 implements MyInterface {
(...)
}
@MyQualifier2
public class Bar2 implements MyInterface {
(...)
}
Это позволит внедрить конкретную реализацию следующим образом:
@Inject
@MyQualifier1
MyInterface target;
Теперь вы вводите MyInterface
квалифицированный с @MyQualifier1
, Во время выполнения его Тип будет Bar1
в этом случае.
Другим подходом, если вы хотите решить во время выполнения, какая реализация вам нужна, будет использование Instance
:
@Inject
Instance<MyInterface> unqualifiedInstance;
void do(){
/// first attach the qualifier, we missed at the injection-point:
Instance qualifiedInstance = instance.select(new AnnotationLiteral<MyQualifier2>(){})
/// Now you have a qualified Instance, which is a new Object without touching the unqualifiedInstance!
MyInterface target = qualifiedInstance.get();
/// so you can decide which implementation you need by passing the qualifier per select-method. in this case its bar2
target.doIt();
}
Если вам нужна дополнительная помощь с квалификаторами, вы можете найти документацию по сварке и особенно главу 4.3 и следующую полезную информацию. http://docs.jboss.org/weld/reference/latest/en-US/html/injection.html