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

时间:2017-04-14 03:34:18

标签: java java-annotations

我创建了一个名为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是使用注释的类文字,如果可以应用,则映射类是嵌套类对象。

2 个答案:

答案 0 :(得分:0)

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

希望这有帮助

答案 1 :(得分:0)

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

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

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

希望这有助于某人。我在这篇文章中找到了答案:Modify a class definition's annotation string parameter at runtime。看看吧!