Интерфейс поставщика услуг в Java Enterprise

1

Я хотел бы закодировать очень модульную фабрику с использованием интерфейса поставщика услуг, поэтому без необходимости изменять каждый раз, когда сама фабрика.

Чтобы сделать это, я хотел бы получить список всех Concrete Classes, которые реализуют интерфейс, и решать во время выполнения, какой из них использовать при вызове метода в каждом, пока у меня не будет подходящего исполнителя.

Пример: у меня есть interface Poligon
и Class Triangle implements Poligon Concrete Class Triangle implements Poligon. Дискриминационным методом будет:

boolean isSuitableFor(int i) {
    if (i == 3) 
      return true; 
    else 
      return false;
}

В Java SE я могу сделать это с помощью ServiceLoader: в среде Enterprise, как я могу найти весь класс реализации и во время выполнения, решите использовать его реализацию, если это подходит? Спасибо!

Теги:
cdi
java-ee
ejb

1 ответ

1

Есть несколько способов решить эту проблему с помощью CDI.

Во-первых, если метод isSuitableFor так же прост, как вы перечисляете, вы можете использовать Qualifier с значением @Nonbinding для указанного в списке int и просто искать реализацию с этим значением классификатора. Скажем, что определитель является @Vertices а значение для Triangle равно 3, поэтому квалификатор становится:

@Qualifier
@Target({ TYPE, METHOD, PARAMETER, FIELD })
@Retention(RUNTIME)
@Documented
public @interface Vertices {
    @Nonbinding int value();
}

И Треугольник становится:

@Vertices(3)
public class Triangle implements Polygon{
}

И вы получите ссылку на него через:

@Inject
@Vertices(3)
private Polygon polygon;

Или вы можете создать AnnotationLiteral для вершин и вручную просмотреть его через экземпляр.

Другой способ - перебрать все экземпляры, например:

@Inject
@Any
private Instance<Polygon> polygons;

for(Polygon p : polygons) {
    if(p.isSuitableFor(x)) {
        // do something.
    }
}

Это предполагает, что все многоугольники являются зарегистрированными бобами. Это будет медленным для большого числа полигонов.

Третий способ - использовать событие, а не квалифицировать класс, квалифицировать метод наблюдателя. Например

@Inject
private Event<SomePayload> somePayload;


// later on
somePayload.select(new VerticesLiteral(3)).fire(somePayload);

// and the observer method in Triangle
public void handle(@Observes @Vertices(3) SomePayload somePayload) { ... }

// and in square
public void handle(@Observes @Vertices(4) SomePayload somePayload) { ... }

Ещё вопросы

Сообщество Overcoder
Наверх
Меню