2015-05-25 5 views
0

Я хочу создать аннотацию (для которой я могу установить какой-то идентификатор), которую я могу наложить на переменную, и написать метод, который возвращает метод getter или setter этой переменной с помощью аннотаций setted id;Явная пользовательская аннотация для поиска методов

В качестве примера я сделал что-то подобное, но только для метода, поэтому мне нужны две аннотации для метода setter и getter или добавление дополнительных параметров в одну аннотацию. Может быть, можно создать одну аннотацию для переменной, а затем найти метод, который мне нужен (сеттер или геттер)?

Что удалось сделать:

класс Аннотация:

public @interface FieldRawValue { 

    String value() default ""; 
} 

Модель класса с добытчиками и сеттеров (с аннотацией для геттеров):

общественный класс PajamuModel простирается AbstractModel {

private String id; 
private String pajamuType; 
private String pajamuSource; 
private Date pajamuData; 
private double pajamuSuma; 
private String valiuta; 
private String note; 

@FieldRawValue(value = "pajamuType") 
public String getPajamuType() { 
    return pajamuType; 
} 

public void setPajamuType(String pajamuType) { 
    this.pajamuType = pajamuType; 
} 

@FieldRawValue(value = "pajamuSource") 
public String getPajamuSource() { 
    return pajamuSource; 
} 

public void setPajamuSource(String pajamuSource) { 
    this.pajamuSource = pajamuSource; 
} 

@FieldRawValue(value = "pajamuData") 
public Date getPajamuData() { 
    return pajamuData; 
}... 

Метод, который возвращает данные по значению аннотаций:

public class AbstractModel { 

public Object get(String fieldName) { 
    Class<? extends AbstractModel> obj = this.getClass(); 

    for (Method method : obj.getDeclaredMethods()) { 
     if (method.isAnnotationPresent(FieldRawValue.class)) { 
      FieldRawValue annotation = method 
        .getAnnotation(FieldRawValue.class); 
      if (annotation.value().equals(fieldName)) { 
       try { 
        return method.invoke(obj); 
       } catch (IllegalAccessException | IllegalArgumentException 
         | InvocationTargetException e) { 
        e.printStackTrace(); 
        return null; 
       } 
      } 
     } 
    } 

    return null; 
} 

Btw, не тестируется get(String fieldName) метод, но я ожидаю, что это работает.

. Можно ли задать аннотацию для переменной, а затем найти метод set или get, когда мне нужно?

ответ

2

Я не уверен, почему вы хотите, чтобы дублировать имя_поль и иметь его в аннотации, однако здесь решение (требуется Java8):

public class AbstractModel { 

    public Object get(String fieldName) throws InvocationTargetException, IllegalAccessException { 
     FieldRawValue fieldRawValueAnnotation = validateExistsAndGetFieldRawValueAnnotation(fieldName); 

     String fieldRawValueString = fieldRawValueAnnotation.value(); 

     Optional<Method> getterMethodOptional = Stream.of(getClass().getMethods()) 
       .filter(method1 -> method1.getName().equalsIgnoreCase("get" + fieldRawValueString)) 
       .findFirst(); 

     return getterMethodOptional 
       .orElseThrow(() -> new RuntimeException("No getter found for @FieldRawValue with value: " + fieldRawValueString)) 
       .invoke(this); 
    } 

    public Object set(String fieldName, Object value) throws InvocationTargetException, IllegalAccessException { 
     FieldRawValue fieldRawValueAnnotation = validateExistsAndGetFieldRawValueAnnotation(fieldName); 

     String fieldRawValueString = fieldRawValueAnnotation.value(); 

     Optional<Method> getterMethodOptional = Stream.of(getClass().getMethods()) 
       .filter(method1 -> method1.getName().equalsIgnoreCase("set" + fieldRawValueString)) 
       .findFirst(); 

     return getterMethodOptional 
       .orElseThrow(() -> new RuntimeException("No setter found for @FieldRawValue with value: " + fieldRawValueString)) 
       .invoke(this, value); 
    } 

    private FieldRawValue validateExistsAndGetFieldRawValueAnnotation(String fieldName) { 
     Class<? extends AbstractModel> obj = this.getClass(); 

     FieldRawValue fieldRawValueAnnotation = null; 
     try { 
      fieldRawValueAnnotation = obj.getDeclaredField(fieldName).getAnnotation(FieldRawValue.class); 
     } catch (NoSuchFieldException e) { 
      new RuntimeException("Field not found: " + fieldName); 
     } 

     if(fieldRawValueAnnotation == null){ 
      throw new RuntimeException("FieldRawValue annotation not found for a field: " + fieldName); 
     } 
     return fieldRawValueAnnotation; 
    } 

модель + Использование:

public class TestModel extends AbstractModel{ 

    @FieldRawValue("test2") 
    private String test; 

    public String getTest2() { 
     return test; 
    } 

    public void setTest2(String test) { 
     this.test = test; 
    } 

    public static void main(String[] args) throws InvocationTargetException, IllegalAccessException { 
     TestModel testModel = new TestModel(); 

     Object tst = testModel.get("test"); //== null 
     testModel.set("test", "newVal"); //sets new value 
     testModel.get("test"); //== "newVal 
    } 

} 
+0

Хорошо, спасибо вы, как я понимаю, нет необходимости в аннотации. – Edgar

+0

Правильно, вы можете вызвать getClass(). GetDeclaredField (fieldName), и если поле существует, попытайтесь найти getter/setter для него – rgrebski

Смежные вопросы