【2020年4月22日】关于AnnotatedElement,你知道多少?
温馨提示:
本文最后更新于 2020年08月25日,已超过 1,543 天没有更新。若文章内的图片失效(无法正常加载),请留言反馈或直接联系我。
关于AnnotatedElement,你了解多少?
首先看一下它的位置所在
再看一下官网的解释,直接上英文
* Represents an annotated element of the program currently running in this
* VM. This interface allows annotations to be read reflectively. All
* annotations returned by methods in this interface are immutable and
* serializable. The arrays returned by methods of this interface may be modified
* by callers without affecting the arrays returned to other callers.
其实就是表示在jvm中当前程序中被注解的元素,这些接口注解可以通过反射去读取
这个吧可能理解不了多少,但是它却可以用在很多地方,比如Class、Method、Field、Constructor等等地方,那么为什么呢?
通过查看它的实现类,发现确实有很多
当你查看Class的时候,你会发现
public final class Class<T> implements java.io.Serializable,
GenericDeclaration,
Type,
AnnotatedElement
是不是实现了接口?
其他的依次类推
再看一下Annotation,关于这个接口,又了解多少?
其实官网都说了很明了
* The common interface extended by all annotation types. Note that an
* interface that manually extends this one does <i>not</i> define
* an annotation type. Also note that this interface does not itself
* define an annotation type.
在使用工具类的时候,发现一个问题,上源码
public class AnnotationUtil {
/**
* 将指定的被注解的元素转换为组合注解元素
*
* @param annotationEle 注解元素
* @return 组合注解元素
*/
public static CombinationAnnotationElement toCombination(AnnotatedElement annotationEle) {
if (annotationEle instanceof CombinationAnnotationElement) {
return (CombinationAnnotationElement) annotationEle;
}
return new CombinationAnnotationElement(annotationEle);
}
/**
* 获取指定注解
*
* @param annotationEle {@link AnnotatedElement},可以是Class、Method、Field、Constructor、ReflectPermission
* @param isToCombination 是否为转换为组合注解
* @return 注解对象
*/
public static Annotation[] getAnnotations(AnnotatedElement annotationEle, boolean isToCombination) {
return (null == annotationEle) ? null : (isToCombination ? toCombination(annotationEle) : annotationEle).getAnnotations();
}
/**
* 获取指定注解
*
* @param <A> 注解类型
* @param annotationEle {@link AnnotatedElement},可以是Class、Method、Field、Constructor、ReflectPermission
* @param annotationType 注解类型
* @return 注解对象
*/
public static <A extends Annotation> A getAnnotation(AnnotatedElement annotationEle, Class<A> annotationType) {
return (null == annotationEle) ? null : toCombination(annotationEle).getAnnotation(annotationType);
}
/**
* 获取指定注解默认值<br>
* 如果无指定的属性方法返回null
*
* @param <T> 注解值类型
* @param annotationEle {@link AccessibleObject},可以是Class、Method、Field、Constructor、ReflectPermission
* @param annotationType 注解类型
* @return 注解对象
* @throws UtilException 调用注解中的方法时执行异常
*/
public static <T> T getAnnotationValue(AnnotatedElement annotationEle, Class<? extends Annotation> annotationType) throws UtilException {
return getAnnotationValue(annotationEle, annotationType, "value");
}
/**
* 获取指定注解属性的值<br>
* 如果无指定的属性方法返回null
*
* @param <T> 注解值类型
* @param annotationEle {@link AccessibleObject},可以是Class、Method、Field、Constructor、ReflectPermission
* @param annotationType 注解类型
* @param propertyName 属性名,例如注解中定义了name()方法,则 此处传入name
* @return 注解对象
* @throws UtilException 调用注解中的方法时执行异常
*/
public static <T> T getAnnotationValue(AnnotatedElement annotationEle, Class<? extends Annotation> annotationType, String propertyName) throws UtilException {
final Annotation annotation = getAnnotation(annotationEle, annotationType);
if (null == annotation) {
return null;
}
final Method method = ReflectUtil.getMethodOfObj(annotation, propertyName);
if (null == method) {
return null;
}
return ReflectUtil.invoke(annotation, method);
}
/**
* 获取指定注解中所有属性值<br>
* 如果无指定的属性方法返回null
*
* @param annotationEle {@link AnnotatedElement},可以是Class、Method、Field、Constructor、ReflectPermission
* @param annotationType 注解类型
* @return 注解对象
* @throws UtilException 调用注解中的方法时执行异常
*/
public static Map<String, Object> getAnnotationValueMap(AnnotatedElement annotationEle, Class<? extends Annotation> annotationType) throws UtilException {
final Annotation annotation = getAnnotation(annotationEle, annotationType);
if (null == annotation) {
return null;
}
final Method[] methods = ReflectUtil.getMethods(annotationType, new Filter<Method>() {
@Override
public boolean accept(Method t) {
if (ArrayUtil.isEmpty(t.getParameterTypes())) {
// 只读取无参方法
final String name = t.getName();
// 跳过自有的几个方法
return (false == "hashCode".equals(name)) //
&& (false == "toString".equals(name)) //
&& (false == "annotationType".equals(name));
}
return false;
}
});
final HashMap<String, Object> result = new HashMap<>(methods.length, 1);
for (Method method : methods) {
result.put(method.getName(), ReflectUtil.invoke(annotation, method));
}
return result;
}
/**
* 获取注解类的保留时间,可选值 SOURCE(源码时),CLASS(编译时),RUNTIME(运行时),默认为 CLASS
*
* @param annotationType 注解类
* @return 保留时间枚举
*/
public static RetentionPolicy getRetentionPolicy(Class<? extends Annotation> annotationType) {
final Retention retention = annotationType.getAnnotation(Retention.class);
if (null == retention) {
return RetentionPolicy.CLASS;
}
return retention.value();
}
/**
* 获取注解类可以用来修饰哪些程序元素,如 TYPE, METHOD, CONSTRUCTOR, FIELD, PARAMETER 等
*
* @param annotationType 注解类
* @return 注解修饰的程序元素数组
*/
public static ElementType[] getTargetType(Class<? extends Annotation> annotationType) {
final Target target = annotationType.getAnnotation(Target.class);
if (null == target) {
return new ElementType[]{ElementType.TYPE, //
ElementType.FIELD, //
ElementType.METHOD, //
ElementType.PARAMETER, //
ElementType.CONSTRUCTOR, //
ElementType.LOCAL_VARIABLE, //
ElementType.ANNOTATION_TYPE, //
ElementType.PACKAGE//
};
}
return target.value();
}
/**
* 是否会保存到 Javadoc 文档中
*
* @param annotationType 注解类
* @return 是否会保存到 Javadoc 文档中
*/
public static boolean isDocumented(Class<? extends Annotation> annotationType) {
return annotationType.isAnnotationPresent(Documented.class);
}
/**
* 是否可以被继承,默认为 false
*
* @param annotationType 注解类
* @return 是否会保存到 Javadoc 文档中
*/
public static boolean isInherited(Class<? extends Annotation> annotationType) {
return annotationType.isAnnotationPresent(Inherited.class);
}
}
以及
public class CombinationAnnotationElement implements AnnotatedElement, Serializable {
private static final long serialVersionUID = 1L;
/** 元注解
* set是个接口,需要通过实现类HashSet 2020年4月21日
*
* 初始化了这个7个注解
* 作为一个Set<Class ? extends Annotation> 初始化的集合 2020年4月21日
* */
private static final Set<Class<? extends Annotation>> META_ANNOTATIONS = CollUtil.newHashSet(Target.class, //
Retention.class, //
Inherited.class, //
Documented.class, //
SuppressWarnings.class, //
Override.class, //
Deprecated.class//
);
/** 注解类型与注解对象对应表 */
private Map<Class<? extends Annotation>, Annotation> annotationMap;
/** 直接注解类型与注解对象对应表 */
private Map<Class<? extends Annotation>, Annotation> declaredAnnotationMap;
/**
* 构造
*
* @param element 需要解析注解的元素:可以是Class、Method、Field、Constructor、ReflectPermission
*/
public CombinationAnnotationElement(AnnotatedElement element) {
init(element);
}
@Override
public boolean isAnnotationPresent(Class<? extends Annotation> annotationClass) {
return annotationMap.containsKey(annotationClass);
}
@Override
@SuppressWarnings("unchecked")
public <T extends Annotation> T getAnnotation(Class<T> annotationClass) {
Annotation annotation = annotationMap.get(annotationClass);
return (annotation == null) ? null : (T) annotation;
}
@Override
public Annotation[] getAnnotations() {
final Collection<Annotation> annotations = this.annotationMap.values();
return annotations.toArray(new Annotation[annotations.size()]);
}
@Override
public Annotation[] getDeclaredAnnotations() {
final Collection<Annotation> annotations = this.declaredAnnotationMap.values();
return annotations.toArray(new Annotation[annotations.size()]);
}
/**
* 初始化
*
* @param element 元素
*/
private void init(AnnotatedElement element) {
final Annotation[] declaredAnnotations = element.getDeclaredAnnotations();
this.declaredAnnotationMap = new HashMap<>();
parseDeclared(declaredAnnotations);
final Annotation[] annotations = element.getAnnotations();
if (declaredAnnotations.equals(annotations)){
System.out.println("true");
}else{
System.out.println("false");
}
//这两个其实是new出来的,虽然这两个值相同,但是地址对象是不同的
if(ObjectUtil.equal(declaredAnnotations, annotations)) {
this.annotationMap = this.declaredAnnotationMap;
}else {
this.annotationMap = new HashMap<>();
parse(annotations);
}
}
/**
* 进行递归解析注解,直到全部都是元注解为止
*
* @param annotations Class, Method, Field等
*/
private void parseDeclared(Annotation[] annotations) {
Class<? extends Annotation> annotationType;
// 直接注解
for (Annotation annotation : annotations) {
annotationType = annotation.annotationType();
if (false == META_ANNOTATIONS.contains(annotationType)) {
//所以这里面只会包含自己定义的或者排除那七个已经定义的的注解 2020年4月21日
declaredAnnotationMap.put(annotationType, annotation);
//递归处理
parseDeclared(annotationType.getDeclaredAnnotations());
}
}
}
/**
* 进行递归解析注解,直到全部都是元注解为止
*
* @param annotations Class, Method, Field等
*/
private void parse(Annotation[] annotations) {
Class<? extends Annotation> annotationType;
for (Annotation annotation : annotations) {
annotationType = annotation.annotationType();
if (false == META_ANNOTATIONS.contains(annotationType)) {
annotationMap.put(annotationType, annotation);
parse(annotationType.getAnnotations());
}
}
}
}
你调试的时候发现有时候这两个value是相等的,但是equals是不同的,为什么?
final Annotation[] declaredAnnotations = element.getDeclaredAnnotations();
this.declaredAnnotationMap = new HashMap<>();
parseDeclared(declaredAnnotations);
final Annotation[] annotations = element.getAnnotations();
这就需要你对源码调试的理解了。
正文到此结束
- 本文标签: Java
- 本文链接: http://www.unknowtime.top/article/189
- 版权声明: 本文由仓颉大哥原创发布,转载请遵循《署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0)》许可协议授权