Java 自定义注解查找方法
Java custom annotation to find methods
我想创建注释(我可以为它设置某种 id),我可以把它放在变量上,然后写方法 return getter 或 setter 方法这个变量的注释设置 id;
例如,我做了类似的东西,但只针对方法,所以我需要为 setter 和 getter 方法提供两个注释,或者向一个注释添加更多参数。也许可以为变量创建一个注释,然后找到我需要的方法(setter 或 getter)?
我设法做到的:
注解class:
public @interface FieldRawValue {
String value() default "";
}
模型 class,具有 getters 和 setters(带有 getters 的注释):
public class 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;
}...
方法,其中 returns 数据按注释值:
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;
}
顺便说一句,未测试 get(String fieldName)
方法,但我希望它有效。
那么可不可以在变量上设置注解,然后在需要的时候再找set或者get方法呢?
我不确定为什么要复制字段名并将其放在注释中,但这是解决方案(需要 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
}
}
我想创建注释(我可以为它设置某种 id),我可以把它放在变量上,然后写方法 return getter 或 setter 方法这个变量的注释设置 id;
例如,我做了类似的东西,但只针对方法,所以我需要为 setter 和 getter 方法提供两个注释,或者向一个注释添加更多参数。也许可以为变量创建一个注释,然后找到我需要的方法(setter 或 getter)?
我设法做到的:
注解class:
public @interface FieldRawValue {
String value() default "";
}
模型 class,具有 getters 和 setters(带有 getters 的注释):
public class 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;
}...
方法,其中 returns 数据按注释值:
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;
}
顺便说一句,未测试 get(String fieldName)
方法,但我希望它有效。
那么可不可以在变量上设置注解,然后在需要的时候再找set或者get方法呢?
我不确定为什么要复制字段名并将其放在注释中,但这是解决方案(需要 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
}
}