2010-12-15 33 views
46

Bir sınıfın bazı üye değişkeninin açıklamalarını bilmek istiyorum, bir sınıfı anlamak için BeanInfo beanInfo = Introspector.getBeanInfo(User.class) kullanın ve belirli bir özelliği bulmak için BeanInfo.getPropertyDescriptors() kullanın ve tesisin Sınıfını almak için Sınıf type = propertyDescriptor.getPropertyType()'u kullanın.Üye değişkeni ek açıklamaları nasıl alınır?

Ancak üye değişkenine ek açıklamaların nasıl ekleneceğini bilmiyorum?

type.getAnnotations() ve type.getDeclaredAnnotations()'u denedim, ancak her ikisi de istediğim gibi değil, Sınıf'ın ek açıklamalarını döndürdü. Örneğin:

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 
{ 
    ... 
} 

Ben adresin ek açıklama almak istiyorum: @column değil sınıf Adres ek açıklama (@Entity, @ tablo, @Cache). Nasıl elde edilir? Teşekkürler.

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

burada böyle görünüyor gibi, DB nesneleri kopyalamak varsa faydalı olabilir @Bozho Benim yöntemim. Farklı bir DB öğesi olması gerekiyorsa, kopya aynı kimliğe sahip olamaz. Genel bir kopya algoritması, Annotation '@Id' ile her şeyi hariç tutabilir. – Hok

cevap

8

Sen User sınıfın tüm üye alan almak için yansıma kullanmak içlerinden yineleme ve bunların ek açıklamalar böyle

şey bulmak zorunda:

propertyDescriptor.getReadMethod().getDeclaredAnnotations(); 

özel alanın açıklamaları alınıyor kötü bir fikir gibi görünüyor ... özellik bile alan tarafından desteklenen veya almazsa ne farklı bir isimle bir alan tarafından destekleniyor mu? Bu davaları görmezden bile, özel eşyalara bakarak soyutlamayı kırarsınız.

+1

Teşekkürler, ancak clazz'm hiçbir public argüman yok ... (Üzgünüm bundan bahsetmedi). Yani, clazz.newInstance() çalışmaz. – smallufo

+1

Sadece clazz.newInstance() satırını atlayın, neden mkoryak bunu içerdiğinden emin değilim - hiçbir şey tarafından kullanılmıyor. – qualidafial

+1

oops, kodu doğru yapıştırmamıştım. Bu, kullanılan – mkoryak

5

Sen alıcı yöntemine ek açıklamalar alabilirsiniz:

+0

Teşekkürler, ama dersin kodunu değiştiremezsem ne olur? Ya özel alanın ek açıklamalarını almak zorunda kalırsam? – smallufo

+0

@smallufo Neden buna ihtiyacın olduğunu merak ediyorum. Ek açıklamalar özel alanlarda olsaydı, onlar hakkında bilmek istemiyordunuz. –

+3

Merhaba, çünkü kodlarımız bir sürü JPA'nın eğitimlerini takip ediyor. Özel alanlarda ek açıklamaları doğrudan ekleyen çoğu JPA öğreticisi/kitap. Ve kazmak istediğim bu JPA ek açıklamaları. – 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(){ 

    } 
} 

Ve test sınıfı:

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()); 
     } 
    } 

} 

Umarım yardımcı olur ...

;-)

71

Herkes sorunu anlatılmaktadır bir almak ile nütasyonlar, ancak problem ek açıklamalarınızın tanımıdır. Eğer açıklama tanımına bir @Retention(RetentionPolicy.RUNTIME) eklemek gerekir:

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

Yoksa bu yardımcı olacak bu

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(); 
} 

Umut deneyebilirsin. Özel bir ek açıklama olup olmadığını öğrenmek istiyorsanız,

+6

Java 6 veya 7'de PropertyDescriptor için API'da getAnnotations() 'ı göremiyorum. Bir şeyi özlüyor muyum? http://docs.oracle.com/javase/7/docs/api/java/beans/PropertyDescriptor.html –

+0

getReadMethod() –

12

. Sen bunu yapabilirsiniz:

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); 

     } 

Ve böylece diğer ek açıklamaları için ...

ben yardım birisini umarım.

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

}