2016-06-12 12 views
2

私はカスタムアノテーションを持っている:Springのカスタム注釈に基づくメソッド呼び出し?

@Target(ElementType.METHOD) 
@Retention(RetentionPolicy.RUNTIME) 
public @interface Controller { 
    EventType[] events() default EventType.MESSAGE; 
} 

、以下のようにそれらを使用して、クラスBのメソッドがあります

@Controller(events = {EventType.MESSAGE, EventType.DIRECT_MESSAGE}) 
public void onMessage(Message msg) { } 

@Controller(events = {EventType.STAR_ADDED}) 
public void onStarAdded(Message msg) { } 

を、私は、アノテーションに基づいて上記の方法を呼び出したいevents別のクラスからの値A。言い換えれば、クラスがタイプSTAR_ADDEDのイベントを受け取ったとき、クラスBのすべてのメソッドを、@Controller(events = {EventType.STAR_ADDED})というアノテーションで呼び出したいとします。

私はJavaでこれを行う方法を知っていますが、スプリングはこれを行うためのAPIを提供していますか?はいの場合は、コードスニペットも役立ちます。

答えて

3

解決方法1:

yourEvent.handleMessage(service, message); 
:あなたは "アクティブ" イベントが何であるかを知っているあなたの他のクラスでは、

enum EventType { 
    MESSAGE { 
     @Override 
     public void handleMessage(Service service, Message message) { 
      service.onMessage(message); 
     } 
    }, 
    STAR_ADDED { 
     @Override 
     public void handleMessage(Service service, Message message) { 
      service.onStarAdded(message); 
     } 

     public abstract void handleMessage(Service service, Message message); 
    } 
} 

:あなたはまた、このような何かを行うことができ

解決策2:

春には何かが正確にあるかどうか分かりません。それ以外の場合は反射も使用できます。私は本当に、次のために適用されるとは思わない

for(Method method: Service.class.getDeclaredMethods()){ 
    Controller annotation = m.getAnnotation(Controller.class); 
    for(EventType event: annotation.events()){ 
     if(event.equals(yourActiveEventType)){ 
      method.invoke(service, message); 
     } 
     return ... 
    } 
} 

ヒント(ない溶液)3:ここではリフレクションを使った例です(私はあまり反射せず=>列挙型上記の溶液を好みます)あなたのシナリオが、私はそれを言及したいと思った... Spring AOPは、注釈付きメソッドが呼び出されると(あなたのシナリオとは逆のもの)、この答えをチェックすることができますが、あなた:aspectj-pointcut-for-all-methods-of-a-class-with-specific-annotation

@Around("execution(@Controller * com.exemple.YourService.*(..))") 
public Object aroundServiceMethodAdvice(final ProceedingJoinPoint pjp) 
    throws Throwable { 
    // perform actions before 

    return pjp.proceed(); 

    // perform actions after 
} 

解決策4:(コメントの後に追加)

org.reflectionsに

<dependency> 
    <groupId>org.reflections</groupId> 
    <artifactId>reflections</artifactId> 
    <version>0.9.10</version> 
</dependency> 

例を使用:

Service service = ...; 
Message message = ...; 

Set<Method> methods = 
     ReflectionUtils.getMethods(Service.class, ReflectionUtils.withAnnotation(Controller.class),ReflectionUtils.withParametersAssignableTo(Message.class)); 

for(Method m: methods){ 
    Controller controller = m.getAnnotation(Controller.class); 
    for(EventType eventType: controller.value()){ 
     if(EventType.MESSAGE.equals(eventType)){ 
      m.invoke(service, message); 
     } 
    } 
} 

これは、すでにここで、(サービスオブジェクトへの参照を保持することを前提としていあなたの方法は)。これは多少デザインにバインドされているとして、あなたの「サービス」が、スプリングが管理されている場合は、春を使用しているので

、あなたは春のコンテキストからインスタンスを得ることができ、あなたは、自分自身でそれを試してみる必要があるでしょう:

@Autowired 
private ApplicationContext appContext; 

Reflections r = new Reflections(new MethodAnnotationsScanner(), "com.your.package"); 
Set<Method> methods = r.getMethodsAnnotatedWith(Controller.class); 
for(Method m: methods){ 
    Controller controller = m.getAnnotation(Controller.class); 
    for(EventType eventType: controller.value()){ 
     if(EventType.MESSAGE.equals(eventType)){ 
      String className = m.getDeclaringClass().getSimpleName(); 
      className = className.replaceFirst(className.substring(0,1), className.substring(0,1).toLowerCase()); 
      Object service = appContext.getBean(className); 
      m.invoke(service, message); 
     } 
    } 
} 

これは、クラスがスプリング管理されており、デフォルトのラクテルケース名を使用してコンテキストに追加されている場合に機能します。

ロジックを簡素化することができますが、主要な要素はそこにあると思います。

+0

はい、あなたの最初の方法は良いですが、私はクラスBのメソッド名を制御できません。あなたはスプリングフレームワークで見つかった '@ Controller'アノテーションのようなものを作成したいと思うかもしれません。だから私の最初の方法は、私が望んでいないそれぞれのイベントの種類ごとに別々のメソッドを持つ必要があります。第2に、2つの異なるイベントで同じアクションが実行されると、コードが繰り返されます。 –

+0

私は、反射(2番目のコードのサンプル)が選択の武器かもしれない参照してください! – alexbt

+0

または、おそらくAroundInvoke/aspectJここにリンクがあります(私の答えは例を編集しています):http://docs.spring.io/spring/docs/current/spring-framework-reference/html/aop.html – alexbt

関連する問題