Java ee interface conditional inject

狂风中的少年 提交于 2019-12-23 17:10:16

问题


I have the following interface:

public interface ResultEvaluationInterface {
    public void evaluateResults(Event e);
}

and I want to inject in my class depending on my Event.type different classes with the same implementation. Something like that:

@Stateless
@LocalBean    
public class ResultEvaluation implements ResultEvaluationInterface {

    @Override
    public void evaluateResults(Event e) {
        switch (e.getType()) {
            case Type.Running:
               // inject and call ResultEvaluationRunningEJB.evaluateResults(e)
            case Type.Swimming:
               // inject and call ResultEvaluationSwimmingEJB.evaluateResults(e)
            default:
               throw new UnsupportedOperationException("Not supported yet.");
        }
    }

}

ResultEvaluationRunningEJB and ResultEvaluationSwimmingEJB both implement the interface. Anybody has got a good idea how to do that in a good way?


回答1:


If you really want to use a hard coded if statement to switch between prod and dev events you could use CDI Qualifiers simply inject the two implementations into a Facade:

@Stateless
@LocalBean    
public class ResultEvaluationFacade {

    @Inject
    @Development
    private ResultEvalutationInterface dev;

    @Inject
    @Production
    private ResultEvalutionInterface prod;

    @Override
    public void evaluateResults(Event e) {
        switch (e.getType()) {
            case Type.Production:
               prod.evaluteResult(e);
               break;
            case Type.Development:
               dev.evaluteResult(e);
               break;
            default:
               throw new UnsupportedOperationException("Not supported yet.");
        }
    }

}

And define your two implementations:

@Development
public class ResultEvaluationDevelopment implements ResultEvaluationInterface {
   ...
}

@Production
public class ResultEvaluationDevelopment implements ResultEvaluationInterface {
   ...
}

However I would consider using a mock maven project to house the two separate implementations instead.

Alternatively you could use different CDI Event types, something like this.

public void observeDevEvent(@Observe DevEvent event) {
   //do stuff.
}

public void observeProdEvent(@Observe ProdEvent event) {
   //do stuff
}

Firing the event would look something like this:

@Inject
private Event<ProdEvent> prodEvent;

public void someMethod() {
   ProdEvent pe = new ProdEvent()
   // set some data on ProdEvent
   prodEvent.fire(pe);
}

Note events can also work with Qualifiers, so you could also add a Qualifier annotation to the Event instead of implementing two different types of event.

@Inject
@Production
private Event<MyEvent> event;

And listen for @Prodcution events;

public void handleProdEvent(@Observer @Production MyEvent myEvent) {
    // do Stuff.
}

For lazy instantiation of beans you can use CDI Instance injection.

@Inject
private Instance<BeanA> beanA;

....

public void doStuff(Event e) {
   ...
   case Type.Production:
            //lazily evaluates and instantiatiates bean.
            beanA.get().evaluateResult(e);
}



回答2:


Note: I have not confirmed that this works, but you should be able to work something out with this.

You could use dynamic CDI event dispatching:

public class EventDispatcher {

    @Inject
    BeanManager beanManager;

    public void handle(MyEvents mytype) {
        beanManager.fireEvent(mytype, mytype.getQualifiyer());
    }
}

You can reference your qualifiers in your event enum something like this:

public enum MyEvents {

    EVENTA(new EventA() {
        @Override
        public Class<? extends Annotation> annotationType() {
            return this.getClass();
        }
    }),
    EVENTB (new EventB() {
        @Override
        public Class<? extends Annotation> annotationType() {
            return this.getClass();
        }
    });

    private final Annotation annotation;

    MyEvents(Annotation annotation) {
        this.annotation = annotation;
    }
    public Annotation getQualifiyer() {
        return annotation;
    }

};

The qualifiers look something like this:

@Qualifier
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.PARAMETER,ElementType.FIELD})
public @interface EventA {

}

That way you could simply add observer methods to the event processing beans:

public class EventProcessorA {
   ...
   public void handleEvent(@Observer @BeanA MyEvents myevent) {
       ...
   }
}

Instead of injecting 20-30 in one dispatcher with a giant switch statement.



来源:https://stackoverflow.com/questions/31474570/java-ee-interface-conditional-inject

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!