Как сделать вывод информации в пользовательской аннотации с Java

Я создал пользовательскую аннотацию под названием CrudSearchable и определил там некоторые атрибуты. Однако атрибуты, которые я назначаю, уже видны из компонента. Есть ли способ, которым я могу получить эти значения без необходимости переопределять их вручную?

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

Где атрибут - это имя атрибута, parentClass - это литерал класса, использующий аннотацию, а сопоставленный класс - это объект вложенного класса, если он применим.

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

Похоже, что многие изменяют значения вместо того, чтобы пользователь определял их, но я считаю, что это сделает код более удобным для пользователя.

Надеюсь, это кому-нибудь поможет. Я нашел ответ на этот пост: измените параметр строки аннотации определения класса во время выполнения. Проверьте это!

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

Надеюсь это поможет

Другие вопросы по тегам