Java企业中的服务提供者接口

Java企业中的服务提供者接口,java,jakarta-ee,ejb,cdi,Java,Jakarta Ee,Ejb,Cdi,我想通过使用服务提供者接口来编写一个非常模块化的工厂,这样就不必每次修改工厂本身 为此,我希望收到实现接口的所有具体类的列表,并在运行时通过每个接口中的方法调用决定使用哪个类,直到找到合适的实现者为止 示例:我有一个接口Poligon 一个具体的类三角形实现Poligon。判别方法是: boolean isSuitableFor(int i) { if (i == 3) return true; else return false; } 在Java

我想通过使用服务提供者接口来编写一个非常模块化的工厂,这样就不必每次修改工厂本身

为此,我希望收到实现接口的所有具体类的列表,并在运行时通过每个接口中的方法调用决定使用哪个类,直到找到合适的实现者为止

示例:我有一个
接口Poligon

一个具体的
类三角形实现Poligon
。判别方法是:

boolean isSuitableFor(int i) {
    if (i == 3) 
      return true; 
    else 
      return false;
}
在JavaSE中,我可以使用ServiceLoader实现:在企业环境中,如何找到所有实现类并在运行时决定使用其实现(如果合适)?
谢谢

使用CDI,我可以想出几种方法来解决这个问题

首先,如果
isSuitableFor
方法与您列出的方法一样简单,您可以使用
限定符
@Nonbinding
值来表示列出的int,只需使用该限定符值查找实现即可。假设限定符是
@顶点
,而
三角形
的值是
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
@任何
私有实例多边形;
用于(多边形p:多边形){
如果(第(x)页){
//做点什么。
}
}
这假设所有多边形都是注册bean。对于大量多边形,这将很慢

第三种方法是使用事件,而不是限定类,而是限定观察者方法。例如

@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) { ... }
@Inject
私有事件负载;
//后来
somePayload.select(newverticesliteral(3)).fire(somePayload);
//以及三角形中的观测器方法
公共无效句柄(@Observes@顶点(3)SomePayload SomePayload){…}
//在广场上
公共无效句柄(@Observes@顶点(4)SomePayload SomePayload){…}