Есть ли способ попросить 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

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