Javax注解处理:检查注解类型是否是另一种类型的子类型
Javax Annotation Processing: Check if an annotated type is a sub-type of another type
我正在创建一个 AnnotationProcessor,我需要检查注释类型是否是指定 class 的子类型。
注释:
public @interface Component {
Class<?> supertype();
}
示例:(正确)
@Component(supertype = MyInterface.class)
public class MyClass implements MyInterface {
// ...
}
示例:(不正确,这不能编译,因为 MyClass
不是 String
的子类型)
@Component(supertype = String.class)
public class MyClass implements MyInterface {
}
我知道我无法获得带注释的 Class
,因为它尚未编译。
你没有在你的问题中提到它,但我假设你 运行 进入 TypeMirror
问题。
这是一个非常老旧的解决方案,用于获取 supertype
字段的 TypeMirror
,并将其与类型的基础 class:
进行比较
@Override
public boolean process(Set<? extends TypeElement> set, RoundEnvironment roundEnvironment) {
for (Element element : roundEnvironment.getElementsAnnotatedWith(Component.class)) {
// TODO: Ensure element is a class before continuing
TypeElement typeElement = (TypeElement) element;
Component componentAnnotation = typeElement.getAnnotation(Component.class);
TypeMirror superType = null;
try {
// Hack to quickly get to TypeMirror of the annotation property
componentAnnotation.supertype();
} catch (MirroredTypeException mte) {
superType = mte.getTypeMirror();
}
// TODO: superType null check
Set<TypeMirror> validTypes = Sets.newHashSet(typeElement.getInterfaces());
validTypes.add(typeElement.getSuperclass());
if (!validTypes.contains(superType)) {
// TODO: throw something better
throw new IllegalArgumentException(typeElement.toString() + " does not implement or inherit from "
+ superType.toString() + " declared in @Component annotation");
}
}
return true;
}
如果我是你,我会仔细研究一下,看看现在是否有更好的选择,但如果没有,这将解决你的问题。
这个版本不依赖于异常,它使用了 Element.getAnnotationMirrors
,这可能是为了这种类型的使用。虽然它更冗长:
@Override
public boolean process(Set<? extends TypeElement> set, RoundEnvironment roundEnvironment) {
for (Element element : roundEnvironment.getElementsAnnotatedWith(Component.class)) {
// TODO: Ensure element is a class before continuing
TypeMirror superType = null;
boolean found = false;
for (AnnotationMirror mirror : element.getAnnotationMirrors()) {
TypeElement annotationElement = (TypeElement) mirror.getAnnotationType().asElement();
if (annotationElement.getQualifiedName().contentEquals(Component.class.getName())) {
found = true;
for (Map.Entry<? extends ExecutableElement, ? extends AnnotationValue> kv :
mirror.getElementValues().entrySet()) {
ExecutableElement member = kv.getKey();
if (member.getKind() == ElementKind.METHOD &&
member.getSimpleName().contentEquals("supertype")) {
superType = (TypeMirror) kv.getValue().getValue();
break;
}
}
}
if (found) {
break;
}
}
// TODO: superType null check
TypeElement typeElement = (TypeElement) element;
Set<TypeMirror> validTypes = Sets.newHashSet(typeElement.getInterfaces());
validTypes.add(typeElement.getSuperclass());
if (!validTypes.contains(superType)) {
// TODO: throw something better
throw new IllegalArgumentException(typeElement.toString() + " does not implement or inherit from "
+ superType.toString() + " declared in @Component annotation");
}
}
return true;
}
使用如下代码获取注解中class值的TypeMirror
public Optional<TypeMirror> getClassValueFromAnnotation(Element element, Class<? extends Annotation> annotation, String paramName) {
for (AnnotationMirror am : element.getAnnotationMirrors()) {
if (types.isSameType(am.getAnnotationType(), elements.getTypeElement(annotation.getCanonicalName()).asType())) {
for (Map.Entry<? extends ExecutableElement, ? extends AnnotationValue> entry : am.getElementValues().entrySet()) {
if (paramName.equals(entry.getKey().getSimpleName().toString())) {
AnnotationValue annotationValue = entry.getValue();
return Optional.of((DeclaredType) annotationValue.getValue());
}
}
}
}
return Optional.empty();
}
然后使用此代码检查它是否是特定 class
的超类型
/**
* A wrapper over {@link Types#isAssignable(TypeMirror, TypeMirror)} which will apply type erasure on the targetClass before calling the wrapped method.
*
* @param typeMirror a {@link javax.lang.model.type.TypeMirror} object.
* @param targetClass a {@link java.lang.Class} object.
* @return a boolean.
*/
public boolean isAssignableFrom(TypeMirror typeMirror, Class<?> targetClass) {
return types.isAssignable(typeMirror, types.erasure(elements.getTypeElement(targetClass.getCanonicalName()).asType()));
}
我正在创建一个 AnnotationProcessor,我需要检查注释类型是否是指定 class 的子类型。 注释:
public @interface Component {
Class<?> supertype();
}
示例:(正确)
@Component(supertype = MyInterface.class)
public class MyClass implements MyInterface {
// ...
}
示例:(不正确,这不能编译,因为 MyClass
不是 String
的子类型)
@Component(supertype = String.class)
public class MyClass implements MyInterface {
}
我知道我无法获得带注释的 Class
,因为它尚未编译。
你没有在你的问题中提到它,但我假设你 运行 进入 TypeMirror
问题。
这是一个非常老旧的解决方案,用于获取 supertype
字段的 TypeMirror
,并将其与类型的基础 class:
@Override
public boolean process(Set<? extends TypeElement> set, RoundEnvironment roundEnvironment) {
for (Element element : roundEnvironment.getElementsAnnotatedWith(Component.class)) {
// TODO: Ensure element is a class before continuing
TypeElement typeElement = (TypeElement) element;
Component componentAnnotation = typeElement.getAnnotation(Component.class);
TypeMirror superType = null;
try {
// Hack to quickly get to TypeMirror of the annotation property
componentAnnotation.supertype();
} catch (MirroredTypeException mte) {
superType = mte.getTypeMirror();
}
// TODO: superType null check
Set<TypeMirror> validTypes = Sets.newHashSet(typeElement.getInterfaces());
validTypes.add(typeElement.getSuperclass());
if (!validTypes.contains(superType)) {
// TODO: throw something better
throw new IllegalArgumentException(typeElement.toString() + " does not implement or inherit from "
+ superType.toString() + " declared in @Component annotation");
}
}
return true;
}
如果我是你,我会仔细研究一下,看看现在是否有更好的选择,但如果没有,这将解决你的问题。
这个版本不依赖于异常,它使用了 Element.getAnnotationMirrors
,这可能是为了这种类型的使用。虽然它更冗长:
@Override
public boolean process(Set<? extends TypeElement> set, RoundEnvironment roundEnvironment) {
for (Element element : roundEnvironment.getElementsAnnotatedWith(Component.class)) {
// TODO: Ensure element is a class before continuing
TypeMirror superType = null;
boolean found = false;
for (AnnotationMirror mirror : element.getAnnotationMirrors()) {
TypeElement annotationElement = (TypeElement) mirror.getAnnotationType().asElement();
if (annotationElement.getQualifiedName().contentEquals(Component.class.getName())) {
found = true;
for (Map.Entry<? extends ExecutableElement, ? extends AnnotationValue> kv :
mirror.getElementValues().entrySet()) {
ExecutableElement member = kv.getKey();
if (member.getKind() == ElementKind.METHOD &&
member.getSimpleName().contentEquals("supertype")) {
superType = (TypeMirror) kv.getValue().getValue();
break;
}
}
}
if (found) {
break;
}
}
// TODO: superType null check
TypeElement typeElement = (TypeElement) element;
Set<TypeMirror> validTypes = Sets.newHashSet(typeElement.getInterfaces());
validTypes.add(typeElement.getSuperclass());
if (!validTypes.contains(superType)) {
// TODO: throw something better
throw new IllegalArgumentException(typeElement.toString() + " does not implement or inherit from "
+ superType.toString() + " declared in @Component annotation");
}
}
return true;
}
使用如下代码获取注解中class值的TypeMirror
public Optional<TypeMirror> getClassValueFromAnnotation(Element element, Class<? extends Annotation> annotation, String paramName) {
for (AnnotationMirror am : element.getAnnotationMirrors()) {
if (types.isSameType(am.getAnnotationType(), elements.getTypeElement(annotation.getCanonicalName()).asType())) {
for (Map.Entry<? extends ExecutableElement, ? extends AnnotationValue> entry : am.getElementValues().entrySet()) {
if (paramName.equals(entry.getKey().getSimpleName().toString())) {
AnnotationValue annotationValue = entry.getValue();
return Optional.of((DeclaredType) annotationValue.getValue());
}
}
}
}
return Optional.empty();
}
然后使用此代码检查它是否是特定 class
的超类型 /**
* A wrapper over {@link Types#isAssignable(TypeMirror, TypeMirror)} which will apply type erasure on the targetClass before calling the wrapped method.
*
* @param typeMirror a {@link javax.lang.model.type.TypeMirror} object.
* @param targetClass a {@link java.lang.Class} object.
* @return a boolean.
*/
public boolean isAssignableFrom(TypeMirror typeMirror, Class<?> targetClass) {
return types.isAssignable(typeMirror, types.erasure(elements.getTypeElement(targetClass.getCanonicalName()).asType()));
}