2010-12-15 10 views
46

クラスのメンバ変数の注釈を知りたい場合は、BeanInfo beanInfo = Introspector.getBeanInfo(User.class)を使用してクラスをイントロスペクションし、BeanInfo.getPropertyDescriptors()を使用して特定のプロパティを見つけ、クラスtype = propertyDescriptor.getPropertyType()を使用してプロパティのクラスを取得します。メンバ変数のアノテーションを取得する方法は?

しかし、私はメンバ変数に注釈を追加する方法を知らないのですか?

私はtype.getAnnotations()type.getDeclaredAnnotations()を試しましたが、どちらもクラスの注釈を返します。たとえば:@Column、クラスではなく住所の注釈(@Entity、@Table、@Cache):

class User 
{ 
    @Id 
    private Long id; 

    @Column(name="ADDRESS_ID") 
    private Address address; 

    // getters , setters 
} 

@Entity 
@Table(name = "Address") 
@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE) 
class Address 
{ 
    ... 
} 

私はアドレスの注釈を取得したいです。それを達成する方法?ありがとう。

public void getAnnotations(Class clazz){ 
    for(Field field : clazz.getDeclaredFields()){ 
     Class type = field.getType(); 
     String name = field.getName(); 
     field.getDeclaredAnnotations(); //do something to these 
    } 
} 
+1

ここケースのようだとしてあなたは、DBオブジェクトをコピーする場合に便利かもしれません@Bozhoマイウェイ。別のDBエンティティになるはずのコピーは、同じIDを持つことはできません。一般的なコピーアルゴリズムは、注釈 '@Id'を持つものを除外することができます。 – Hok

答えて

61

それは(と、それはコンパイル)Class.newInstanceに依存しない以外は、このコードmkoryakのバリエーションです。

for(Field field : cls.getDeclaredFields()){ 
    Class type = field.getType(); 
    String name = field.getName(); 
    Annotation[] annotations = field.getDeclaredAnnotations(); 
} 

も参照してください:http://docs.oracle.com/javase/tutorial/reflect/class/classMembers.html

8

あなたは、Userクラスのすべてのメンバーのフィールドを取得するためにリフレクションを使用し、それらを反復処理し、その注釈このような

何かを見つけることがあります。

propertyDescriptor.getReadMethod().getDeclaredAnnotations(); 

プライベートフィールドの注釈を取得することは悪い考えです。プロパティがフィールドで裏付けされていない場合、または別の名前のフィールドに裏付けられていますか?そのような場合を無視しても、あなたは私的なものを見ることによって抽象を破っています。

+1

ありがとうございますが、私のclazzには引数なしのpublicコンストラクタはありません...(申し訳ありませんでした。したがって、clazz.newInstance()は機能しません。 – smallufo

+1

clazz.newInstance()行を省略すると、なぜmkoryakにそれが含まれているのか分かりません。何にも使われていません。 – qualidafial

+1

おっと、正しいコードを貼り付けていませんでした。実際に使用されています – mkoryak

5

あなたはgetterメソッドに注釈を取得することができます:

+0

ありがとうございますが、クラスのコードを変更できない場合はどうすればよいですか?プライベートフィールドの注釈を取得する必要がある場合はどうすればよいですか? – smallufo

+0

@smallufoなぜあなたがこれを必要としているのかが分かりました。アノテーションがプライベートフィールドにあった場合は、それらについて知ることを意図していませんでした。 –

+3

こんにちは、私たちのコードは多くのJPAのチュートリアルに従っているからです。ほとんどのJPAチュートリアル/書籍は、プライベートフィールドに注釈を直接追加します。そして私が掘り下げたいのは、これらのJPAアノテーションです。 – smallufo

2
package be.fery.annotation; 

import javax.persistence.Column; 
import javax.persistence.Entity; 
import javax.persistence.Id; 
import javax.persistence.PrePersist; 

@Entity 
public class User { 
    @Id 
    private Long id; 

    @Column(name = "ADDRESS_ID") 
    private Address address; 

    @PrePersist 
    public void doStuff(){ 

    } 
} 

とテストクラス:

package be.fery.annotation; 

import java.lang.annotation.Annotation; 
import java.lang.reflect.Field; 
import java.lang.reflect.Method; 

public class AnnotationIntrospector { 

    public AnnotationIntrospector() { 
     super(); 
    } 

    public Annotation[] findClassAnnotation(Class<?> clazz) { 
     return clazz.getAnnotations(); 
    } 

    public Annotation[] findMethodAnnotation(Class<?> clazz, String methodName) { 

     Annotation[] annotations = null; 
     try { 
      Class<?>[] params = null; 
      Method method = clazz.getDeclaredMethod(methodName, params); 
      if (method != null) { 
       annotations = method.getAnnotations(); 
      } 
     } catch (SecurityException e) { 
      e.printStackTrace(); 
     } catch (NoSuchMethodException e) { 
      e.printStackTrace(); 
     } 
     return annotations; 
    } 

    public Annotation[] findFieldAnnotation(Class<?> clazz, String fieldName) { 
     Annotation[] annotations = null; 
     try { 
      Field field = clazz.getDeclaredField(fieldName); 
      if (field != null) { 
       annotations = field.getAnnotations(); 
      } 
     } catch (SecurityException e) { 
      e.printStackTrace(); 
     } catch (NoSuchFieldException e) { 
      e.printStackTrace(); 
     } 
     return annotations; 
    } 

    /** 
    * @param args 
    */ 
    public static void main(String[] args) { 
     AnnotationIntrospector ai = new AnnotationIntrospector(); 
     Annotation[] annotations; 
     Class<User> userClass = User.class; 
     String methodDoStuff = "doStuff"; 
     String fieldId = "id"; 
     String fieldAddress = "address"; 

     // Find class annotations 
     annotations = ai.findClassAnnotation(be.fery.annotation.User.class); 
     System.out.println("Annotation on class '" + userClass.getName() 
       + "' are:"); 
     showAnnotations(annotations); 

     // Find method annotations 
     annotations = ai.findMethodAnnotation(User.class, methodDoStuff); 
     System.out.println("Annotation on method '" + methodDoStuff + "' are:"); 
     showAnnotations(annotations); 

     // Find field annotations 
     annotations = ai.findFieldAnnotation(User.class, fieldId); 
     System.out.println("Annotation on field '" + fieldId + "' are:"); 
     showAnnotations(annotations); 

     annotations = ai.findFieldAnnotation(User.class, fieldAddress); 
     System.out.println("Annotation on field '" + fieldAddress + "' are:"); 
     showAnnotations(annotations); 

    } 

    public static void showAnnotations(Annotation[] ann) { 
     if (ann == null) 
      return; 
     for (Annotation a : ann) { 
      System.out.println(a.toString()); 
     } 
    } 

} 

それが役に立てば幸い...

;-)

71

誰もが問題を説明します取得するとアノテーションの定義に問題があります。あなたは、アノテーションの定義@Retention(RetentionPolicy.RUNTIME)に追加する必要があります。

@Retention(RetentionPolicy.RUNTIME) 
@Target(ElementType.FIELD) 
public @interface MyAnnotation{ 
    int id(); 
} 
-2

それとも、これが役立ちます。この

try { 
    BeanInfo bi = Introspector.getBeanInfo(User.getClass()); 
    PropertyDescriptor[] properties = bi.getPropertyDescriptors(); 
    for(PropertyDescriptor property : properties) { 
     //One way 
     for(Annotation annotation : property.getAnnotations()){ 
      if(annotation instanceof Column) { 
       String string = annotation.name(); 
      } 
     } 
     //Other way 
     Annotation annotation = property.getAnnotation(Column.class); 
     String string = annotation.name(); 
    } 
}catch (IntrospectonException ie) { 
    ie.printStackTrace(); 
} 

希望を試みることができます。

+6

Java 6または7の「PropertyDescriptor」のAPIのどこでも 'getAnnotations()'が表示されません。何か不足していますか? http://docs.oracle.com/javase/7/docs/api/java/beans/PropertyDescriptor.html –

+0

getReadMethod() –

12

アノテーションの特定が存在するかどうかを知る必要がある場合。あなたはそうすることができます:

Field[] fieldList = obj.getClass().getDeclaredFields(); 

     boolean isAnnotationNotNull, isAnnotationSize, isAnnotationNotEmpty; 

     for (Field field : fieldList) { 

      //Return the boolean value 
      isAnnotationNotNull = field.isAnnotationPresent(NotNull.class); 
      isAnnotationSize = field.isAnnotationPresent(Size.class); 
      isAnnotationNotEmpty = field.isAnnotationPresent(NotEmpty.class); 

     } 

などなど他の注釈のための...

私は、ヘルプ誰かを願っています。

0

import org.slf4j.Logger; 
import org.slf4j.LoggerFactory; 

import java.beans.BeanInfo; 
import java.beans.Introspector; 
import java.beans.PropertyDescriptor; 

public class ReadAnnotation { 
    private static final Logger LOGGER = LoggerFactory.getLogger(ReadAnnotation.class); 

    public static boolean hasIgnoreAnnotation(String fieldName, Class entity) throws NoSuchFieldException { 
     return entity.getDeclaredField(fieldName).isAnnotationPresent(IgnoreAnnotation.class); 
    } 

    public static boolean isSkip(PropertyDescriptor propertyDescriptor, Class entity) { 
     boolean isIgnoreField; 
     try { 
      isIgnoreField = hasIgnoreAnnotation(propertyDescriptor.getName(), entity); 
     } catch (NoSuchFieldException e) { 
      LOGGER.error("Can not check IgnoreAnnotation", e); 
      isIgnoreField = true; 
     } 
     return isIgnoreField; 
    } 

    public void testIsSkip() throws Exception { 
     Class<TestClass> entity = TestClass.class; 
     BeanInfo beanInfo = Introspector.getBeanInfo(entity); 

     for (PropertyDescriptor propertyDescriptor : beanInfo.getPropertyDescriptors()) { 
      System.out.printf("Field %s, has annotation %b", propertyDescriptor.getName(), isSkip(propertyDescriptor, entity)); 
     } 
    } 

} 
関連する問題