简体   繁体   English

Java Enterprise中的服务提供者接口

[英]Service Provider Interface in Java Enterprise

I would like to code a very modular factory through the use of a Service Provider Interface, so without having to modify every time the Factory itself. 我想通过使用服务提供者接口对一个非常模块化的工厂进行编码,因此不必每次都修改工厂本身。

To do that I would like to receive the list of all the Concrete Classes that implement an interface and decide at runtime which one to use through a method call in each until I have a suitable Implementer. 为此,我希望收到实现接口的所有具体类的列表,并在运行时通过每个方法的调用来决定使用哪个具体类,直到我拥有合适的Implementer。

Example: I have an interface Poligon 示例:我有一个interface Poligon
and a Concrete Class Triangle implements Poligon . 和一个Class Triangle implements Poligon的具体Class Triangle implements Poligon The discriminant method would be: 判别方法为:

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

In Java SE I can do it using ServiceLoader: in an Enterprise environment how can I find all the implementing class and at runtime decide to use its implementation if suitable? 在Java SE中,我可以使用ServiceLoader做到这一点:在企业环境中,如何找到所有实现类,并且在运行时决定是否酌情使用其实现? Thx! 谢谢!

There are a couple of ways I can think of to solve this using CDI. 我可以考虑使用CDI解决此问题的几种方法。

First, if the isSuitableFor method is as simple as you list, you can use a Qualifier with a @Nonbinding value for the int listed, and simply look up the implementation with that qualifier value. 首先,如果isSuitableFor方法与您列出的一样简单,则可以对列出的int使用带有@Nonbinding值的Qualifier ,并只需使用该限定符值查找实现。 Let's say that the qualifier is @Vertices and the value for Triangle is 3 , so then the qualifier becomes: 假设限定符为@Vertices并且Triangle值为3 ,那么限定符变为:

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

And Triangle becomes: 三角形变成:

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

And you would get a reference to it via: 您将通过以下方式获得对它的引用:

@Inject
@Vertices(3)
private Polygon polygon;

Or you can create an AnnotationLiteral for vertices and manually look it up via instance. 或者,您可以为顶点创建AnnotationLiteral并通过实例手动查找。

Another way, is to iterate through all Instances, like this: 另一种方法是遍历所有实例,如下所示:

@Inject
@Any
private Instance<Polygon> polygons;

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

This assuming that all polygons are registered beans. 假设所有多边形都是注册的bean。 This will be slow for large numbers of polygons. 对于大量的多边形,这将很慢。

The third way is to use an event, and instead of qualifying the class, qualify the observer method. 第三种方法是使用事件,而不是限定类,而是限定观察者方法。 Eg 例如

@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) { ... }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM