3

我对基于泛型的特定事件处理有一个想法,但似乎 Weld 无法处理它们。我问了谷歌,但找不到替代的 CDI 扩展。

问题:是否有 CDI 扩展,可以处理泛型事件的事件传播?

以下是我遇到的明确问题。

我有三个常规事件,EntityCreated、EntityChanged 和 EntityDeleted。它们的基类定义如下:

public abstract class DatabaseEvent<TargetType> {

    public TargetType target;

    public DatabaseEvent(TargetType target) {
        this.target = target;
    }
}

然后事件是简单的继承类:

public class EntityCreatedEvent<TargetType> extends DatabaseEvent<TargetType> {

    public EntityCreatedEvent(TargetType target) {
        super(target);
    }
}

我这样解雇他们:

public abstract class MyHome<EntityType> {

    private EntityType entity;

    @Inject
    Event<EntityCreatedEvent<EntityType>> entityCreatedEvent;

    public void fireCreatedEvent() {
        EntityCreatedEvent<EntityType> payload = new EntityCreatedEvent<EntityType>(entity);
        entityCreatedEvent.fire(payload);
    }
}

我想像这样观察它们:

public void handleProjectCreated(@Observes EntityCreatedEvent<Project> event) { ... }

启动服务器时 Weld 告诉我它无法处理泛型类型的事件。CDI 做事的方式是使用额外的限定符而不是泛型来区分它们,例如:

public void handleProjectCreated(@Observes @ProjectEvent EntityCreatedEvent event) { ... }

但是,我从那个MyHome基类触发事件,我不能只用@ProjectEvent: 它可能不是一个项目,而是另一种类型。

到目前为止,我的解决方案是完全跳过该输入并像这样处理它们:

public void handleProjectCreated(@Observes EntityCreatedEvent event) { 
    if(event.target instanceof Project) { ... }
}

这个解决方案还可以,但并不完美。

4

2 回答 2

6

我想您可以使用动态绑定限定符成员来做到这一点。这就是您的代码的样子:

public abstract class MyHome {

    private EntityType entity;

    @Inject
    Event<EntityCreatedEvent> entityCreatedEvent;

    public void fireCreatedEvent() {
        entityCreatedEvent.select(getTypeBinding()).fire(new EntityCreatedEvent(entity));
    }

    private TypeBinding getTypeBinding() {
        return new TypeBinding() {
        public Class<? extends EntityType> value() {return entity.getClass();}
    };
}

@Qualifier
@Target({ PARAMETER, FIELD })
@Retention(RUNTIME)
public @interface EntityTypeQualifier {
    Class<? extends EntityType> value();
}

public abstract class TypeBinding extends AnnotationLiteral<EntityTypeQualifier> implements EntityTypeQualifier {}

//Observers
public void handleEntityType1Created(@Observes @EntityTypeQualifier(EntityType1.class) EntityCreatedEvent event) {}
public void handleEntityType2Created(@Observes @EntityTypeQualifier(EntityType2.class) EntityCreatedEvent event) {}
于 2013-10-02T15:15:22.233 回答
0

正如这个 CDI 问题指出T的那样,如果没有运行时的类型,就不可能触发。

但是,如果您有 的类型T(即您有一个实例),您可以Event用作,并使用Instance动态类型文字选择要触发的事件。

于 2017-05-04T14:41:19.363 回答