2015-01-13 18 views
8

私が知りたいのは、「Springの@Versionedアノテーションが付いているすべてのクラス/メソッド」でした。 Springコンテキストでメソッドレベルのカスタム注釈を見つけよう

は、私は私のカスタムアノテーションを作成し

@Target({ElementType.METHOD, ElementType.TYPE}) 
@Retention(RetentionPolicy.RUNTIME) 
@Documented 
public @interface Versioned { 
    ..... 
} 

、として私はのような方法を見つけるためにJavaリフレクションを使用したときに完璧にの作品この注釈:私は春にアクセスしたとき

for(Method m: obj.getClass().getMethods()){ 
    if(m.isAnnotationPresent(Versioned.class)){ 
     .... // Do something 
    } 

をしかし、それは動作しません。豆と同様のチェックを試みる:

public class VersionScanner implements ApplicationContextAware{ 
    public void setApplicationContext(ApplicationContext applicationContext){ 
     for(String beanName: applicationContext.getBeanDefinitionNames()){ 
      for(Method m: applicationContext.getBean(beanName).getClass().getDeclaredMethods()){ 
       if(m.isAnnotationPresent(Versioned.class){ 
        // This is not WORKING as expected for any beans with method annotated 
       } 
      } 
     } 
    } 
} 

実際、このコードは@RequestMappingなどの他の注釈を検索します。カスタム注釈で間違っていることがわかりません。

+0

Beanはプロキシされていますか? –

+0

私は言いたいのですが、SOFは最低10文字必要です:-) – kamoor

+0

Ok、再現性のある例は最小です。 –

答えて

6

、 CGLIBプロキシでSpring AOPを使用していることが分かりました。そのため、あなたのクラス(@Versionedと注釈を付けられたメソッドを持つ)がプロキシされています。

私はあなたのコードベースでこのソリューションをテストしました。

次のコードを使用すると、問題が解決するはずです。あなたは春CGLIBでプロキシする場合のSpring AOPプロキシの

  • は、任意のプロキシ機構を使用org.springframework.aop.support.AopUtils#isAoPProxy
  • を使用して(ない:プロキシクラスを検出するために

    @Configuration 
    public class VersionScanner implements ApplicationContextAware { 
    
        public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { 
    
         for (String beanName : applicationContext.getBeanDefinitionNames()) { 
          Object obj = applicationContext.getBean(beanName); 
          /* 
          * As you are using AOP check for AOP proxying. If you are proxying with Spring CGLIB (not via Spring AOP) 
          * Use org.springframework.cglib.proxy.Proxy#isProxyClass to detect proxy If you are proxying using JDK 
          * Proxy use java.lang.reflect.Proxy#isProxyClass 
          */ 
          Class<?> objClz = obj.getClass(); 
          if (org.springframework.aop.support.AopUtils.isAopProxy(obj)) { 
    
           objClz = org.springframework.aop.support.AopUtils.getTargetClass(obj); 
          } 
    
          for (Method m : objClz.getDeclaredMethods()) { 
           if (m.isAnnotationPresent(Versioned.class)) { 
            //Should give you expected results 
           } 
          } 
         } 
        } 
    } 
    

    :コードスニペット以下でより多くのオプションを探してください春AOP)を介して、あなたはJDKプロキシを使用してプロキシする場合、使用org.springframework.cglib.proxy.Proxy#isProxyClass

  • 使用java.lang.reflect.Proxy#isProxyClass

私はちょうどあなたのケースでは十分なif状態を書いています。複数のプロキシユーティリティが使用されている場合は、上記の情報に基づいて複数のif-elseの条件を記述する必要があります。

+0

ちょっとしたメモです。条件が不要な場合。 AopUtils.getTargetClass()メソッドはそれをすべて解決します。 – Angad

+0

あなたは正しいですが、応答の後半で述べるように、さまざまな種類のプロキシをテストするために条件が必要な場合... SpringドキュメントAopUtils#getTargetClass: '指定されたBeanインスタンスのターゲットクラスをAOPプロキシであること。 AOPプロキシのターゲットクラスとプレーンクラスelseを返します。 ' – owaism

+0

はい。ユーティリティメソッドは、渡した内容に基づいて、必要なクラス(ターゲットかどうか)を返します。 Spring Aopプロキシは、jdkプロキシまたはcglibプロキシのいずれかです。 – Angad

4

applicationContext.getBean(beanName).getClass()は、あなたのターゲットクラスの周りにSpringが作成するプロキシークラスを提供します。

あなたが望むのは、Spring Beanから対象クラスがあればそれを保持することです。

SpringはAopUtils.classという名前解決のための優れたユーティリティクラスを提供します。以下は

あなたがそれを使用する方法である:あなたがAopUtilsクラスのホールドを取得するためにspring-aopMaven依存関係をインポートする必要があります

for(String beanName: applicationContext.getBeanDefinitionNames()){ 
    Method[] methods = AopUtils.getTargetClass(applicationContext.getBean(beanName)).getDeclaredMethods(); 

    for(Method m: methods){ 
     if(m.isAnnotationPresent(Versioned.class){ 
     } 
    } 
} 

注:あなたのコードを通って行く

<dependency> 
    <groupId>org.springframework</groupId> 
    <artifactId>spring-aop</artifactId> 
    <version>${spring.version}</version> 
</dependency> 
関連する問題