【问题标题】:How to Infer Information in Custom Annotation with Java如何使用 Java 推断自定义注释中的信息
【发布时间】:2017-04-14 03:34:18
【问题描述】:

我创建了一个名为 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是使用注解的类字面量,mapped class是嵌套类对象(如果适用的话)。

【问题讨论】:

    标签: java java-annotations


    【解决方案1】:
    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());
    

    希望对你有帮助

    【讨论】:

    • 感谢您的帖子,但是一旦我对值进行硬编码,我已经能够访问这些元素,但是如果您在 bean 中看到,我将重述课程中可见的信息。我想从注释中获取这个。 e. g @CrudSearchable(attribute="name", parentClass=MockUser.class) 字符串名称;应替换为 @CrudSearchable 字符串名称;我从注释代码中推断出属性名称和类。这可能吗?
    【解决方案2】:

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

    // 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。看看吧!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-08-11
      • 1970-01-01
      • 1970-01-01
      • 2015-02-01
      相关资源
      最近更新 更多