Java 具有子类运行时类型的Fire事件

Java 具有子类运行时类型的Fire事件,java,jakarta-ee,cdi,jsr299,Java,Jakarta Ee,Cdi,Jsr299,我想在CDI中触发一个事件,其类型只能在运行时确定。例如,假设有一个接口A,它实现了类AA和AB。我有两名观察员: public void observeAA(@Observes AA aa) { } public void observeAA(@Observes AB ab) { } 然后是一些活动制作人: @Inject @Any private Event<A> event; public A getPayload(); public void fire() {

我想在CDI中触发一个事件,其类型只能在运行时确定。例如,假设有一个接口
A
,它实现了类
AA
AB
。我有两名观察员:

public void observeAA(@Observes AA aa) {
}

public void observeAA(@Observes AB ab) {
}
然后是一些活动制作人:

@Inject @Any
private Event<A> event;

public A getPayload();

public void fire() {
    this.event.fire(getPayload());
}
但是,它需要一个正确参数化的
对象(如果我错了,请更正),我无法在运行时构建该对象

是否有任何解决方案,或者我必须使用限定符(可能是带有
方法的注释)?

为什么不使用限定符

public void observeA(@Observes A a) {
}
根据“a”实现类决定要做什么

public void observeA(@Observes A a) {
    if (a instanceof AA)
    {
     ...
    }
    else
    ...
}
你为什么不使用

public void observeA(@Observes A a) {
}
根据“a”实现类决定要做什么

public void observeA(@Observes A a) {
    if (a instanceof AA)
    {
     ...
    }
    else
    ...
}

我最终使用了一个带有
成员的限定符

@Qualifier
@Target({TYPE, METHOD, PARAMETER, FIELD})
@Retention(RUNTIME)
public @interface EventType {
    Class<?> value();
}


public class Dispatcher {

    @Inject @Any
    private Event<A> event;

    public void fireEvent(A a) {
            this.event.select(
                    getTypeAnnotation(
                    a.getClass())).fire(a);
    }

    public static EventType getTypeAnnotation(
            final Class<?> type) {
        return (EventType) Proxy.newProxyInstance(
                Thread.currentThread().getContextClassLoader(),
                new Class<?>[]{EventType.class},
                new InvocationHandler() {

            @Override
            public Object invoke(Object proxy, Method method,
                    Object[] args) throws Throwable {
                if (method.equals(
                        EventType.class.getMethod("value"))) {
                    return type;
                } else if (method.equals(Annotation.class.getMethod(
                        "annotationType"))) {
                    return EventType.class;
                } else if (method.getName().equals("hashCode")) {
                    return 127 * "value".hashCode() ^ type.hashCode();
                } else if (method.getName().equals("equals")) {
                    return (args[0] instanceof EventType &&
                            ((EventType)args[0]).value()
                            .equals(type));
                }
                return null;
            }
        });
    }
}

public class X {
    public void observeA(
            @Observes @EventType(AA.class) A a) {
    ...
@限定符
@目标({类型、方法、参数、字段})
@保留(运行时)
public@interface事件类型{
类值();
}
公共类调度器{
@注入@Any
私人活动;
公众活动(A){
this.event.select(
getTypeAnnotation(
a、 getClass())。火灾(a);
}
公共静态事件类型getTypeAnnotation(
最终课程类型){
返回(EventType)Proxy.newProxyInstance(
Thread.currentThread().getContextClassLoader(),
新类[]{EventType.Class},
新的调用处理程序(){
@凌驾
公共对象调用(对象代理、方法、,
对象[]args)抛出可丢弃的{
如果(方法1)等于(
EventType.class.getMethod(“值”)){
返回类型;
}else if(method.equals(Annotation.class.getMethod(
“注释类型”)){
返回EventType.class;
}else if(method.getName().equals(“hashCode”)){
返回127*“value”.hashCode()^type.hashCode();
}else if(method.getName().equals(“equals”)){
返回(args[0]instanceof EventType&&
((EventType)参数[0]).value()
.等于(类型));
}
返回null;
}
});
}
}
公共X类{
公共无效观测(
@观察@EventType(AA.class)A){
...
编辑

这是实例化注释的一种更简单的方法:

public abstract static class ConfigTypeAnnotation
        extends AnnotationLiteral<ConfigType>
        implements ConfigType { }

public static ConfigType getConfigTypeAnnotation(final Class<?> type) {
    return new ConfigTypeAnnotation() {
        @Override
        public Class<?> value() {
            return type;
        }
    };
}
公共抽象静态类ConfigTypeAnnotation
扩展AnnotationLiteral
实现ConfigType{}
公共静态ConfigType getConfigTypeAnnotation(最终类类型){
返回新的ConfigTypeAnnotation(){
@凌驾
公共类值(){
返回类型;
}
};
}

我最后使用了一个带有
类的限定符

@Qualifier
@Target({TYPE, METHOD, PARAMETER, FIELD})
@Retention(RUNTIME)
public @interface EventType {
    Class<?> value();
}


public class Dispatcher {

    @Inject @Any
    private Event<A> event;

    public void fireEvent(A a) {
            this.event.select(
                    getTypeAnnotation(
                    a.getClass())).fire(a);
    }

    public static EventType getTypeAnnotation(
            final Class<?> type) {
        return (EventType) Proxy.newProxyInstance(
                Thread.currentThread().getContextClassLoader(),
                new Class<?>[]{EventType.class},
                new InvocationHandler() {

            @Override
            public Object invoke(Object proxy, Method method,
                    Object[] args) throws Throwable {
                if (method.equals(
                        EventType.class.getMethod("value"))) {
                    return type;
                } else if (method.equals(Annotation.class.getMethod(
                        "annotationType"))) {
                    return EventType.class;
                } else if (method.getName().equals("hashCode")) {
                    return 127 * "value".hashCode() ^ type.hashCode();
                } else if (method.getName().equals("equals")) {
                    return (args[0] instanceof EventType &&
                            ((EventType)args[0]).value()
                            .equals(type));
                }
                return null;
            }
        });
    }
}

public class X {
    public void observeA(
            @Observes @EventType(AA.class) A a) {
    ...
@限定符
@目标({类型、方法、参数、字段})
@保留(运行时)
public@interface事件类型{
类值();
}
公共类调度器{
@注入@Any
私人活动;
公众活动(A){
this.event.select(
getTypeAnnotation(
a、 getClass())。火灾(a);
}
公共静态事件类型getTypeAnnotation(
最终课程类型){
返回(EventType)Proxy.newProxyInstance(
Thread.currentThread().getContextClassLoader(),
新类[]{EventType.Class},
新的调用处理程序(){
@凌驾
公共对象调用(对象代理、方法、,
对象[]args)抛出可丢弃的{
如果(方法1)等于(
EventType.class.getMethod(“值”)){
返回类型;
}else if(method.equals(Annotation.class.getMethod(
“注释类型”)){
返回EventType.class;
}else if(method.getName().equals(“hashCode”)){
返回127*“value”.hashCode()^type.hashCode();
}else if(method.getName().equals(“equals”)){
返回(args[0]instanceof EventType&&
((EventType)参数[0]).value()
.等于(类型));
}
返回null;
}
});
}
}
公共X类{
公共无效观测(
@观察@EventType(AA.class)A){
...
编辑

这是实例化注释的一种更简单的方法:

public abstract static class ConfigTypeAnnotation
        extends AnnotationLiteral<ConfigType>
        implements ConfigType { }

public static ConfigType getConfigTypeAnnotation(final Class<?> type) {
    return new ConfigTypeAnnotation() {
        @Override
        public Class<?> value() {
            return type;
        }
    };
}
公共抽象静态类ConfigTypeAnnotation
扩展AnnotationLiteral
实现ConfigType{}
公共静态ConfigType getConfigTypeAnnotation(最终类类型){
返回新的ConfigTypeAnnotation(){
@凌驾
公共类值(){
返回类型;
}
};
}

我有一个类似的要求,并最终注入BeanManager来触发事件。

我有一个类似的要求,并最终注入BeanManager来触发事件。

因为我无法集中该逻辑。观察者需要更改私有状态,等等。如果(!(AA的实例))我可以做
return;
,但我必须把它放在每个观察者身上。因为我不能集中那个逻辑。观察者需要改变私有状态等等。如果(!(AA的实例))return;
,我可以做
,但我必须把它放在每个观察者身上。