【问题标题】:JavaEE CDI in Weld: Generic Events?Weld 中的 JavaEE CDI:通用事件?
【发布时间】:2013-10-08 17:35:09
【问题描述】:

我有一个基于泛型的特定事件处理的想法,但似乎 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) { ... }
}

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

【问题讨论】:

  • Fabricio 提到您需要使用限定符。原因是类型擦除。在运行时,所有这些精心设计的泛型类型都不适用于类型系统在反射期间使用(除非您经历了非常长的时间并且有使用这些类型的方法等)和事件期间的类型检查。最好使用限定符。

标签: events generics java-ee-6 cdi weld


【解决方案1】:

作为this CDI issue points,如果在运行时没有T 的类型,就无法触发。

但是,如果您有T 的类型(即您有一个实例),您可以use the Event as an Instance,并使用dynamic type literal 选择要触发的事件。

【讨论】:

    【解决方案2】:

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-09-19
      • 2013-05-01
      • 1970-01-01
      • 2016-02-14
      • 1970-01-01
      • 2013-08-10
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多