恕我直言,您应该将使用 @Version 注释注释的字段类型放在该类中。我认为这也适用于继承,开箱即用。
如果您事先不知道类型,我会使用标准反射。我将遍历所有声明的字段,并检查注释是否包含 @Version 注释。如果没有找到,检查 superclass,直到找到...
public static Field getVersionField(Object entity) {
Class<?> myClass = entity.getClass();
do {
Field[] fields = myClass.getDeclaredFields();
for(Field field:fields) {
if(field.getAnnotation(Version.class)!=null) {
return field;
}
}
} while((myClass=myClass.getSuperclass())!=null);
return null;
}
当心虽然Class.getFields()似乎是一个更好的选择,因为它只返回公共字段,但它不起作用:
返回一个包含 Field 对象的数组,该数组反映了此 Class 对象表示的类或接口的所有可访问公共字段。
编辑以上仅适用于在字段上严格使用@Version 注释的情况。然而,正如 Konstantin Pribluda 指出的那样,这个注释也可以放在方法上,这意味着两件事:
- 方法也必须检查
- 接口也必须检查,因为方法可以由接口定义......
这也意味着我们的简单循环必须转化为递归图遍历......
public static Method getVersionMethod(Class<?> myClass) {
Method[] methods = myClass.getDeclaredMethods();
for(Method method : methods) {
if(method.getAnnotation(Version.class)!=null) {
return method;
}
}
if(myClass.getSuperclass()!=null) {
Class<?> returned = getVersionMethod(myClass.getSuperclass());
if(returned!=null) {
return returned;
}
}
for(Class<?> interfaceToCheck : myClass.getInterfaces()) {
Class<?> returned = getVersionMethod(interfaceToCheck);
if(returned!=null) {
return returned;
}
}
return null;
}