# Spring AnnotationUtils - Author: [HuiFer](https://github.com/huifer) - 源码阅读仓库: [SourceHot-Spring](https://github.com/SourceHot/spring-framework-read) - `org.springframework.core.annotation.AnnotationUtils`提供了注解相关的方法 1. getAnnotation: 获取注解 1. findAnnotation: 寻找注解 1. getValue: 获取属性值 1. getDefaultValue: 获取默认值 ## getAnnotation - 测试用例如下 ```java @Test public void findMethodAnnotationOnLeaf() throws Exception { Method m = Leaf.class.getMethod("annotatedOnLeaf"); assertNotNull(m.getAnnotation(Order.class)); assertNotNull(getAnnotation(m, Order.class)); assertNotNull(findAnnotation(m, Order.class)); } ``` - `org.springframework.core.annotation.AnnotationUtils.getAnnotation(java.lang.reflect.Method, java.lang.Class)` ```java /** * Get a single {@link Annotation} of {@code annotationType} from the * supplied {@link Method}, where the annotation is either present * or meta-present on the method. *

Correctly handles bridge {@link Method Methods} generated by the compiler. *

Note that this method supports only a single level of meta-annotations. * For support for arbitrary levels of meta-annotations, use * {@link #findAnnotation(Method, Class)} instead. * * @param method the method to look for annotations on * 被检查的函数 * @param annotationType the annotation type to look for * 需要检测的注解类型 * @return the first matching annotation, or {@code null} if not found * @see org.springframework.core.BridgeMethodResolver#findBridgedMethod(Method) * @see #getAnnotation(AnnotatedElement, Class) */ @Nullable public static A getAnnotation(Method method, Class annotationType) { // 函数 Method resolvedMethod = BridgeMethodResolver.findBridgedMethod(method); // 强制转换 return getAnnotation((AnnotatedElement) resolvedMethod, annotationType); } ``` - method ![image-20200116085344737](../../../images/spring/image-20200116085344737.png) - annotationType ![image-20200116085423073](../../../images/spring/image-20200116085423073.png) ```java @Nullable public static A getAnnotation(AnnotatedElement annotatedElement, Class annotationType) { try { // 获取注解 A annotation = annotatedElement.getAnnotation(annotationType); if (annotation == null) { for (Annotation metaAnn : annotatedElement.getAnnotations()) { annotation = metaAnn.annotationType().getAnnotation(annotationType); if (annotation != null) { break; } } } return (annotation != null ? synthesizeAnnotation(annotation, annotatedElement) : null); } catch (Throwable ex) { handleIntrospectionFailure(annotatedElement, ex); return null; } } ``` - `org.springframework.core.annotation.AnnotationUtils.synthesizeAnnotation(A, java.lang.reflect.AnnotatedElement)` ```java public static A synthesizeAnnotation( A annotation, @Nullable AnnotatedElement annotatedElement) { return synthesizeAnnotation(annotation, (Object) annotatedElement); } ``` ```java /** * 注解是否存在别名,没有直接返回 * * @param annotation 注解 * @param annotatedElement 函数 * @param * @return */ @SuppressWarnings("unchecked") static A synthesizeAnnotation(A annotation, @Nullable Object annotatedElement) { if (annotation instanceof SynthesizedAnnotation || hasPlainJavaAnnotationsOnly(annotatedElement)) { return annotation; } // 具体的注解 Class annotationType = annotation.annotationType(); if (!isSynthesizable(annotationType)) { return annotation; } DefaultAnnotationAttributeExtractor attributeExtractor = new DefaultAnnotationAttributeExtractor(annotation, annotatedElement); InvocationHandler handler = new SynthesizedAnnotationInvocationHandler(attributeExtractor); // Can always expose Spring's SynthesizedAnnotation marker since we explicitly check for a // synthesizable annotation before (which needs to declare @AliasFor from the same package) Class[] exposedInterfaces = new Class[]{annotationType, SynthesizedAnnotation.class}; return (A) Proxy.newProxyInstance(annotation.getClass().getClassLoader(), exposedInterfaces, handler); } ``` -`org.springframework.core.annotation.AnnotationUtils.isSynthesizable` ```java @SuppressWarnings("unchecked") private static boolean isSynthesizable(Class annotationType) { if (hasPlainJavaAnnotationsOnly(annotationType)) { return false; } // 从缓存中获取当前注解,不存在null Boolean synthesizable = synthesizableCache.get(annotationType); if (synthesizable != null) { return synthesizable; } synthesizable = Boolean.FALSE; for (Method attribute : getAttributeMethods(annotationType)) { if (!getAttributeAliasNames(attribute).isEmpty()) { synthesizable = Boolean.TRUE; break; } // 获取返回值类型 Class returnType = attribute.getReturnType(); // 根据返回值做不同处理 if (Annotation[].class.isAssignableFrom(returnType)) { Class nestedAnnotationType = (Class) returnType.getComponentType(); if (isSynthesizable(nestedAnnotationType)) { synthesizable = Boolean.TRUE; break; } } else if (Annotation.class.isAssignableFrom(returnType)) { Class nestedAnnotationType = (Class) returnType; if (isSynthesizable(nestedAnnotationType)) { synthesizable = Boolean.TRUE; break; } } } synthesizableCache.put(annotationType, synthesizable); return synthesizable; } ``` - `org.springframework.core.annotation.AnnotationUtils#getAttributeMethods` ```java static List getAttributeMethods(Class annotationType) { List methods = attributeMethodsCache.get(annotationType); if (methods != null) { return methods; } methods = new ArrayList<>(); // annotationType.getDeclaredMethods() 获取注解中的方法 for (Method method : annotationType.getDeclaredMethods()) { if (isAttributeMethod(method)) { ReflectionUtils.makeAccessible(method); methods.add(method); } } // 缓存 key:注解,value:函数列表 attributeMethodsCache.put(annotationType, methods); // 函数列表 return methods; } ``` - `org.springframework.core.annotation.AnnotationUtils#isAttributeMethod` ```java /** * Determine if the supplied {@code method} is an annotation attribute method. *

* 做3个判断 *

    *
  1. 函数不为空(method != null)
  2. *
  3. 参数列表是不是空(method.getParameterCount() == 0)
  4. *
  5. 返回类型不是void(method.getReturnType() != void.class)
  6. *
* * @param method the method to check * @return {@code true} if the method is an attribute method * @since 4.2 */ static boolean isAttributeMethod(@Nullable Method method) { return (method != null && method.getParameterCount() == 0 && method.getReturnType() != void.class); } ``` - `org.springframework.util.ReflectionUtils#makeAccessible(java.lang.reflect.Method)` ```java @SuppressWarnings("deprecation") // on JDK 9 public static void makeAccessible(Method method) { // 1. 方法修饰符是不是public // 2. 注解是不是public // 3. 是否重写 if ((!Modifier.isPublic(method.getModifiers()) || !Modifier.isPublic(method.getDeclaringClass().getModifiers())) && !method.isAccessible()) { method.setAccessible(true); } } ``` 处理结果 ![image-20200116085726577](../../../images/spring/image-20200116085726577.png) ![image-20200116085737632](../../../images/spring/image-20200116085737632.png) 处理结果和Order定义相同 ```java @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE, ElementType.METHOD, ElementType.FIELD}) @Documented public @interface Order { /** * The order value. *

Default is {@link Ordered#LOWEST_PRECEDENCE}. * * 启动顺序,默认integer最大值 * @see Ordered#getOrder() */ int value() default Ordered.LOWEST_PRECEDENCE; } ``` 最终返回 ![image-20200116085927359](../../../images/spring/image-20200116085927359.png) ## findAnnotation - `org.springframework.core.annotation.AnnotationUtils#findAnnotation(java.lang.reflect.Method, java.lang.Class)` ```java @SuppressWarnings("unchecked") @Nullable public static A findAnnotation(Method method, @Nullable Class annotationType) { Assert.notNull(method, "Method must not be null"); if (annotationType == null) { return null; } // 创建注解缓存,key:被扫描的函数,value:注解 AnnotationCacheKey cacheKey = new AnnotationCacheKey(method, annotationType); // 从findAnnotationCache获取缓存 A result = (A) findAnnotationCache.get(cacheKey); if (result == null) { Method resolvedMethod = BridgeMethodResolver.findBridgedMethod(method); // 寻找注解 result = findAnnotation((AnnotatedElement) resolvedMethod, annotationType); if (result == null) { result = searchOnInterfaces(method, annotationType, method.getDeclaringClass().getInterfaces()); } Class clazz = method.getDeclaringClass(); while (result == null) { clazz = clazz.getSuperclass(); if (clazz == null || clazz == Object.class) { break; } Set annotatedMethods = getAnnotatedMethodsInBaseType(clazz); if (!annotatedMethods.isEmpty()) { for (Method annotatedMethod : annotatedMethods) { if (isOverride(method, annotatedMethod)) { Method resolvedSuperMethod = BridgeMethodResolver.findBridgedMethod(annotatedMethod); result = findAnnotation((AnnotatedElement) resolvedSuperMethod, annotationType); if (result != null) { break; } } } } if (result == null) { result = searchOnInterfaces(method, annotationType, clazz.getInterfaces()); } } if (result != null) { // 处理注解 result = synthesizeAnnotation(result, method); // 添加缓存 findAnnotationCache.put(cacheKey, result); } } // 返回 return result; } ``` - `org.springframework.core.annotation.AnnotationUtils.AnnotationCacheKey` ```java private static final class AnnotationCacheKey implements Comparable { /** * 带有注解的函数或者类 */ private final AnnotatedElement element; /** * 注解 */ private final Class annotationType; public AnnotationCacheKey(AnnotatedElement element, Class annotationType) { this.element = element; this.annotationType = annotationType; } } ``` - `org.springframework.core.annotation.AnnotationUtils#findAnnotation(java.lang.reflect.AnnotatedElement, java.lang.Class)` ```java @Nullable public static A findAnnotation( AnnotatedElement annotatedElement, @Nullable Class annotationType) { // 注解类型不为空 if (annotationType == null) { return null; } // Do NOT store result in the findAnnotationCache since doing so could break // findAnnotation(Class, Class) and findAnnotation(Method, Class). // 寻找注解 A ann = findAnnotation(annotatedElement, annotationType, new HashSet<>()); return (ann != null ? synthesizeAnnotation(ann, annotatedElement) : null); } ``` - `org.springframework.core.annotation.AnnotationUtils#findAnnotation(java.lang.reflect.AnnotatedElement, java.lang.Class, java.util.Set)` ```java @Nullable private static A findAnnotation( AnnotatedElement annotatedElement, Class annotationType, Set visited) { try { // 直接获取注解 A annotation = annotatedElement.getDeclaredAnnotation(annotationType); if (annotation != null) { return annotation; } // 多级注解 for (Annotation declaredAnn : getDeclaredAnnotations(annotatedElement)) { Class declaredType = declaredAnn.annotationType(); // 注解是否 由java.lang.annotation提供 if (!isInJavaLangAnnotationPackage(declaredType) && visited.add(declaredAnn)) { annotation = findAnnotation((AnnotatedElement) declaredType, annotationType, visited); if (annotation != null) { return annotation; } } } } catch (Throwable ex) { handleIntrospectionFailure(annotatedElement, ex); } return null; } ``` ![image-20200116092259944](../../../images/spring/image-20200116092259944.png) - `synthesizeAnnotation`方法就不再重复一遍了可以看上文 ## getValue - 测试用例 ```java @Test public void getValueFromAnnotation() throws Exception { Method method = SimpleFoo.class.getMethod("something", Object.class); Order order = findAnnotation(method, Order.class); assertEquals(1, getValue(order, VALUE)); assertEquals(1, getValue(order)); } ``` - `org.springframework.core.annotation.AnnotationUtils#getValue(java.lang.annotation.Annotation, java.lang.String)` ```java @Nullable public static Object getValue(@Nullable Annotation annotation, @Nullable String attributeName) { if (annotation == null || !StringUtils.hasText(attributeName)) { return null; } try { // 根据attributeName获取注解对应函数 Method method = annotation.annotationType().getDeclaredMethod(attributeName); ReflectionUtils.makeAccessible(method); // 反射执行方法 return method.invoke(annotation); } catch (NoSuchMethodException ex) { return null; } catch (InvocationTargetException ex) { rethrowAnnotationConfigurationException(ex.getTargetException()); throw new IllegalStateException("Could not obtain value for annotation attribute '" + attributeName + "' in " + annotation, ex); } catch (Throwable ex) { handleIntrospectionFailure(annotation.getClass(), ex); return null; } } ``` ```java @Nullable public static Object getValue(Annotation annotation) { return getValue(annotation, VALUE); } ``` ## getDefaultValue - `org.springframework.core.annotation.AnnotationUtils#getDefaultValue(java.lang.annotation.Annotation)` ```java @Nullable public static Object getDefaultValue(Annotation annotation) { return getDefaultValue(annotation, VALUE); } ``` ```java @Nullable public static Object getDefaultValue( @Nullable Class annotationType, @Nullable String attributeName) { if (annotationType == null || !StringUtils.hasText(attributeName)) { return null; } try { // 直接获取defaultValue return annotationType.getDeclaredMethod(attributeName).getDefaultValue(); } catch (Throwable ex) { handleIntrospectionFailure(annotationType, ex); return null; } } ```