如何使用 Java 推断自定义注释中的信息

How to Infer Information in Custom Annotation with Java

我创建了一个名为 CrudSearchable 的自定义注释,并在那里定义了一些属性。但是,我正在分配的属性已经从 bean 中可见。有没有一种方法可以获取这些值而无需手动重新定义它们?

// Bean
public class MockUser {

    @CrudSearchable(attribute = "name", 
                    parentClass = MockUser.class)
    private String name;

    @CrudSearchable(attribute = "group", 
                    parentClass = MockUser.class, 
                    mappedClass = MockGroup.class)
    private MockGroup group;

    // Get/Set, Equals/Hashcode, etc... 
}

// Annotation Class
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface CrudSearchable {

    String attribute();

    boolean searchable() default true;

    Class<?> mappedClass() default CrudSearchable.class;

    Class<?> parentClass() default Object.class;
}

其中 attribute 是属性名称,parentClass 是使用注释的 class 文字,mapped class 是嵌套的 class 对象(如果适用)。

MockUser obj = new MockUser();
Class<?> c = obj.getClass();
Field[] fields = c.getDeclaredFields();       
CrudSearchable annotation = fields[0].getAnnotation(CrudSearchable.class);
System.out.println("attribute: "   + annotation.attribute() + 
                   "searchable: "  + annotation.searchable());

希望对您有所帮助

我在另一个问题上找到了答案。这就是我要找的。

// Put in Reflector.java

/**
 * Changes the annotation value for the given key of the given annotation to newValue and returns
 * the previous value.
 */
@SuppressWarnings("unchecked")
public static Object changeAnnotationValue(Annotation annotation, String key, Object newValue){
    Object handler = Proxy.getInvocationHandler(annotation);
    Field f;
    try {
        f = handler.getClass().getDeclaredField("memberValues");
    } catch (NoSuchFieldException | SecurityException e) {
        throw new IllegalStateException(e);
    }
    f.setAccessible(true);
    Map<String, Object> memberValues;
    try {
        memberValues = (Map<String, Object>) f.get(handler);
    } catch (IllegalArgumentException | IllegalAccessException e) {
        throw new IllegalStateException(e);
    }
    Object oldValue = memberValues.get(key);
    if (oldValue == null || oldValue.getClass() != newValue.getClass()) {
        throw new IllegalArgumentException();
    }
    memberValues.put(key,newValue);
    return oldValue;
}

一旦我有了这个,我就可以在构造函数中调用下面的方法来改变我使用的注释。

// Put in Service Class

public void modifySearchable(Class<?> clazz) {
    for(Field f : clazz.getDeclaredFields()){
        CrudSearchable[] searchableArray = f.getDeclaredAnnotationsByType(CrudSearchable.class);

        for(CrudSearchable searchable : searchableArray){
            if(searchable == null){
                continue;
            }

            Reflector.alterAnnotation(searchable, "attribute", f.getName());
            Reflector.alterAnnotation(searchable, "parentClass", clazz);

            if(!(searchable.mappedAttribute().equals(""))){
                String mappedGetter = "get" + 
                        searchable.mappedAttribute().substring(0, 1).toUpperCase() + 
                        searchable.mappedAttribute().substring(1);

                Reflector.alterAnnotation(searchable, "mappedClass", f.getType());
                Reflector.alterAnnotation(searchable, "mappedGetter", mappedGetter);
            }
        }
    }
}

// Changed Bean

@Id
@GeneratedValue
@Column(name = "MOCK_USER_ID")
private Long id;

@Column(name = "MOCK_USER_NAME")
@CrudSearchable
private String name;

@ManyToOne
@JoinColumn(name = "MOCK_GROUP", nullable = false)
@CrudSearchable(mappedAttribute = "name")
private MockGroup group;

public MockUser(){
    super();
    new Searchable<>().modifySearchable(this.getClass());
}

更改值而不是让用户定义它们似乎很多,但我相信这将使代码更加用户友好。

希望这对某人有所帮助。我在 post: Modify a class definition's annotation string parameter at runtime 上找到了答案。看看吧!