2011-08-04 10 views
2

実行時にのみタイプを判別できるイベントを発生させたいのですが、たとえば、クラスとABを実装するインタフェースAがあるとします。サブクラスランタイムタイプのイベントを起動

public void observeAA(@Observes AA aa) { 
} 

public void observeAA(@Observes AB ab) { 
} 

その後、いくつかのイベントプロデューサ:私は2人のオブザーバーを持って

@Inject @Any 
private Event<A> event; 

public A getPayload(); 

public void fire() { 
    this.event.fire(getPayload()); 
} 

AAAまたはAB(それは周りの他の方法です)のサブタイプでもないので、これは動作しません。

public <U extends T> Event<U> select(Class<U> subtype, Annotation... qualifiers); 

はしかし、それは(私が間違っている場合は、正しい)、私は実行時に構築することはできません正しくパラメータ化Classオブジェクトが必要です:私は、サブタイプを取るselect方法があります気づきました。

修飾子を使用する必要がありますか(おそらくClass<?>メソッドの注釈)。

あなたは「」実装クラスに応じて何をすべきかを決定する

public void observeA(@Observes A a) { 
} 

を使用していないのはなぜ

答えて

1

メンバーはClass<?>メンバーで終了しました。

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

EDIT

これは注釈をインスタンス化する簡単な方法です:

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; 
     } 
    }; 
} 
0

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

私はそのロジックを集中化できないためです。オブザーバーは私的な状態などを変更する必要があります。もし* if(!(インスタンスのAA))が返ります;しかし、私はすべてのオブザーバーにそれを置く必要があります。 – Artefacto

0

私は同様の要件を持っていたし、イベントを発生するBeanManagerを注入することになりました。

関連する問題