我正在尝试编写一个带有批注的简单验证库,该批注使用Java
8中的新TYPE_USE目标。访问这些内容的方法确实很复杂,给我留下了两个非常混乱的代码,它们执行的功能完全相同,但同时与他们的实际意图紧密相关。因此,我决定创建一组简单的类,以非常简单和直观的方式保存此信息。基本上有TypedClass,它是一个Class包装器,但是可以将其强制转换为ListClass(集合或数组)或MapClass,以TypedClass的形式访问其组件(或键/值)。最重要的部分是应该转换的此帮助程序:
static TypedClass<?> create(Field f) {
final TypeResolver typeResolver = new TypeResolver();
ResolvedType type = typeResolver.resolve(f.getGenericType());
return create(f.getAnnotations(), type, f.getAnnotatedType());
}
private static TypedClass<?> create(Annotation[] annotations, ResolvedType type, AnnotatedType at) {
if (type.isArray()) {
AnnotatedType childAnnotatedType = ((AnnotatedArrayType) at).getAnnotatedGenericComponentType();
ResolvedType childType = type.getArrayElementType();
return new ListClass<>(type.getErasedType(), annotations, create(at.getAnnotations(), childType, childAnnotatedType));
} else if (type.isInstanceOf(Collection.class)) {
AnnotatedType childAnnotatedType = ((AnnotatedParameterizedType) at).getAnnotatedActualTypeArguments()[0];
ResolvedType childType = type.typeParametersFor(Collection.class).get(0);
return new ListClass<>(type.getErasedType(), annotations, createForGenerics(childType, childAnnotatedType));
} else if (type.isInstanceOf(Map.class)) {
AnnotatedType[] att = ((AnnotatedParameterizedType) at).getAnnotatedActualTypeArguments();
List<ResolvedType> types = type.typeParametersFor(Map.class);
TypedClass<?> key = createForGenerics(types.get(0), att[0]);
TypedClass<?> value = createForGenerics(types.get(1), att[1]);
return new MapClass<>(type.getErasedType(), annotations, key, value);
}
return new TypedClass<>(type.getErasedType(), annotations);
}
private static TypedClass<?> createForGenerics(ResolvedType childType, AnnotatedType childAnnotatedType) {
return create(childAnnotatedType.getAnnotations(), childType, childAnnotatedType);
}
在这里,我还使用com.fasterxml.classmate中的ResolvedType,它仅用于在Java中的Type和Class之间架起桥梁,这也是一个痛苦。我认为这与问题无关,因为生成的结构还可以,只有注释放错了位置。
看起来工作还不错,除非List或Map中有一个数组。例如:
@First("array") List<@First("string") String> @First("list") [] arrayOfListOfString;
工作正常(注释与相应的类型匹配)。但是当我解析
List<@First("int[]") Integer @First("int") []> listOfArrayOfInteger;
数组和整数都与@First(“ int”)批注关联。
我已经调试了代码,在任何地方都找不到对@First(“ int
[]”)批注的引用。我或者缺少一些非常简单的东西,或者没有任何意义。该代码似乎可以在所有其他情况下使用,甚至是更复杂的情况。我已经尝试了好几个星期,直到最近才找到我认为可行的解决方案。原来,我之前使用的两种耦合方法在这种情况下也不起作用(没有进行此特定测试)。所以现在我很困。
怎么了?
在您的初始通话中,create
您传递的是 字段 注释,而不是的注释AnnotatedType at
。因此,该方法create
负责调用at.getAnnotations()
。如果看一下实现,您会发现它只会在数组情况下这样做。在所有其他情况下,您的方法将逻辑切换为“传入的注释数组是与关联的数组at
”。
问题在于您的第一个示例似乎偶然地起作用。您没有显示@First
注释的声明,但我怀疑@Target
s ElementType.FIELD
和
都允许使用ElementType.TYPE_USE
。在这种情况下,形式的声明
@First("array") List… [] fieldName;
是不明确的并且注释将被记录为 两个
,一个字段注释fieldName
和用于注释List…[]
类型。因此,在第一个示例中无法识别递归过程中丢失一个注释数组的事实,因为它恰好与字段注释匹配。但是,一旦TYPE_USE
只允许注释而不是FIELD
目标注释,则您的代码甚至无法与第一个示例一起使用。
因此,您必须确定传入的批注数组是与at
参数关联的数组还是与周围上下文关联的数组。如果两者都关联起来会更容易,因为在这种情况下,您可以通过让方法检索该数组而不是调用方来完全摆脱该参数。
您应该记住:
TYPE_USE
主要处理注释,则根本不需要处理字段注释这是一个简单,直接的解析代码,可查找所有注释:
public static void fullType(Field f) {
AnnotatedType at = f.getAnnotatedType();
fullType("\t", at);
System.out.println(f.getName());
}
public static void fullType(String header, AnnotatedType at) {
final boolean arrayType = at instanceof AnnotatedArrayType;
if(arrayType) {
fullType(header+"\t",
((AnnotatedArrayType)at).getAnnotatedGenericComponentType());
}
for(Annotation a: at.getAnnotations())
System.out.println(header+a);
if(arrayType) {
System.out.println(header+"[]");
}
else if(at instanceof AnnotatedParameterizedType) {
AnnotatedParameterizedType apt = (AnnotatedParameterizedType)at;
System.out.println(header
+((ParameterizedType)apt.getType()).getRawType().getTypeName());
System.out.println(header+'<');
String subHeader=header+"\t";
for(AnnotatedType typeArg:
apt.getAnnotatedActualTypeArguments())
fullType(subHeader, typeArg);
System.out.println(header+'>');
}
else if(at instanceof AnnotatedTypeVariable) {
// when appearing in a Field’s type, it refers to Class’ type variables
System.out.println(header+at.getType().getTypeName());
}
else if(at instanceof AnnotatedWildcardType) {
System.out.println(header+"?");
final AnnotatedWildcardType awt = (AnnotatedWildcardType)at;
AnnotatedType[] bounds=awt.getAnnotatedLowerBounds();
if(bounds==null || bounds.length==0) {
bounds=awt.getAnnotatedUpperBounds();
if(bounds==null || bounds.length==0) return;
System.out.println(header+"extends");
}
else System.out.println(header+"super");
header+="\t";
for(AnnotatedType b: bounds) fullType(header, b);
}
else {
assert at.getType().getClass()==Class.class;
System.out.println(header+at.getType().getTypeName());
}
}
它可以完美地与您的示例字段一起使用。
我有一个简单的类叫BeaconDao 然而,当我用@service或@component标记beaconDao时,一切都运行得非常好。有人能看出问题所在吗?
问题内容: 我正在尝试使用Java批注,但似乎无法使我的代码认识到其中存在。我究竟做错了什么? 问题答案: 您需要使用注释界面上的@Retention注释将注释指定为运行时注释。 即
问题内容: 我知道有一些关于此的帖子,但是它们大约一年了,没有任何回应。实际上,我们在PostgreSQL 8.4上使用的是Hibernate 4.2.1.Final。我们有两个这样的实体 实体A(顶级层次结构类) 实体B(子类) 如您所见,使用注释了一个实体,但是当使用来获取顶级类时 我们也通过属性获得了B子类。实际上,SQL语句包含。这仍然是Hibernate第四版中的错误,还是我做错了什么?
问题内容: 我从Spring Framework开始,想做一个带有注释的HelloWorld,我已经创建了一个控制器和一个视图,我猜它是基本的hello工作。但是,我想使用注释,因为我不能再使用SimpleFormController(已弃用)。 我收到的错误是Estado HTTP 404-/av/index.jsp 我正在使用Netbeans,并将示例基于它提供的基本模板。我有以下文件,我可以
我有3个测试类如下: 包裹通讯。朱尼特。测试用例; Test3类: Test2类: Test1类: 和一个TestSuite类: 问题是它在从eclipse从JUnit运行TestSuite1类时忽略了Test3类中的@规则标签,因此输出不如预期。为什么它忽略了@规则标签。有没有其他选择来执行所有三种情况?