public static boolean isInJavaLangAnnotationPackage(@Nullable Annotation annotation)
:是否是JDK的注解(String的重载方法,省略)
public static void main(String[] args) { MyAnno myAnno = Eat.class.getAnnotation(MyAnno.class); Target target = MyAnno.class.getAnnotation(Target.class); System.out.println(AnnotationUtils.isInJavaLangAnnotationPackage(myAnno)); //false System.out.println(AnnotationUtils.isInJavaLangAnnotationPackage(target)); //true }
- public static Map<String, Object> getAnnotationAttributes(Annotation annotation):获取这个注解的所有属性值们,用map保存(非常重要)
- public static AnnotationAttributes getAnnotationAttributes(Annotation annotation, boolean classValuesAsString, boolean nestedAnnotationsAsMap):最全的一个方法 classValuesAsString:true表示把Class类型的都转换为String类型,nestedAnnotationsAsMap:true表示连内嵌的注解也解析出来(默认都是false的) 注意此处返回的是AnnotationAttributes,它其实就是个Map,提供了各种更便捷的获取方法:getString、getBoolean等等
- public static AnnotationAttributes getAnnotationAttributes(@Nullable AnnotatedElement annotatedElement, Annotation annotation):annotatedElement表示被标注了后面这个注解的元素,如果不知道,你就传null吧
// 给注解增加属性、有Class属性 也有嵌套属性 @Target({ElementType.METHOD, ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @RequestMapping @Inherited @interface MyAnno { String value() default "this is mine"; Class<? extends Number> clazz() default Integer.class; // 注解类型的属性 Component anno() default @Component; } public static void main(String[] args) { MyAnno myAnno = Eat.class.getAnnotation(MyAnno.class); // 它原理是调用了下面的底层方法 传值为两个false Map<String, Object> myAnnoAttrs = AnnotationUtils.getAnnotationAttributes(myAnno); // 此处可以看到clazz输出的是class类型,并不是字符串。anno也是调用了toString方法,并没有解析内嵌的 System.out.println(myAnnoAttrs); //{clazz=class java.lang.Integer, value=this is mine, anno=@org.springframework.stereotype.Component(value=mytest)} // =====传双true AnnotationAttributes annotationAttributes = AnnotationUtils.getAnnotationAttributes(myAnno, true, true); System.out.println(annotationAttributes); //{clazz=java.lang.Integer, value=this is mine, anno={value=mytest}} // 经过我测试,第一个参数写Object.class都无所谓 结果和上面一样的 // 若哪位小伙伴知道这个参数有不同的解释,请告知哈 AnnotationAttributes classAnno = AnnotationUtils.getAnnotationAttributes(Object.class, myAnno, true, true); System.out.println(classAnno); }
public static Object getValue(Annotation annotation)
:获取注解内指定属性的值
public static void main(String[] args) { MyAnno myAnno = Eat.class.getAnnotation(MyAnno.class); // 个人觉得还不如直接:myAnno.value()呢 哈哈(Spring底层用的Method做的) System.out.println(AnnotationUtils.getValue(myAnno)); //this is mine System.out.println(AnnotationUtils.getValue(myAnno, "clazz")); //class java.lang.Integer System.out.println(AnnotationUtils.getValue(myAnno, "aaa")); //null }
public static Object getDefaultValue(@Nullable Annotation annotation, @Nullable String attributeName)
:和上面相比,这里只拿默认值。若没有设置默认值,那就返回null- public static <A extends Annotation> A synthesizeAnnotation(A annotation, @Nullable AnnotatedElement annotatedElement):提供出一个public的方法,外部也能调用代理指定的注解了(各种重载方法略)
- public static void clearCache():我们也可以手动调用此方法,清除内部的缓存
顺便提一句,其内部有一个私有的静态内部类private static class AliasDescriptor:专程用来处理@AliasFor注解
AnnotatedElementUtils:在AnnotatedElement finding annotations, meta-annotations, and repeatable annotations(@since 4.0)
- public static AnnotatedElement forAnnotations(final Annotation... annotations):给这么多的Annos提供一个适配器(内部就是new了一个AnnotatedElement匿名内部类,没啥特殊的)
- public static Set<String> getMetaAnnotationTypes(AnnotatedElement element, String annotationName):简单的说,就是返回指定Class上面这个注解上的注解(若没有,返回null) 备注:不包含Java的元注解哦~
- public static boolean hasMetaAnnotationTypes(AnnotatedElement element, Class<? extends Annotation> annotationType):
- public static boolean isAnnotated(AnnotatedElement element, Class<? extends Annotation> annotationType):厉害。不管是注解,还是有注解的注解标注了 都返回true
public static void main(String[] args) { Set<String> metaAnnotationTypes = AnnotatedElementUtils.getMetaAnnotationTypes(Child.class, MyAnno.class); System.out.println(metaAnnotationTypes); //[org.springframework.web.bind.annotation.RequestMapping, org.springframework.web.bind.annotation.Mapping] // 请注意此处:因为是元注解types,所以第一个是false,第二个是true System.out.println(AnnotatedElementUtils.hasMetaAnnotationTypes(Child.class, MyAnno.class)); // false System.out.println(AnnotatedElementUtils.hasMetaAnnotationTypes(Child.class, RequestMapping.class)); // true // 注意此处 两个都是true哦~~~ System.out.println(AnnotatedElementUtils.isAnnotated(Child.class, MyAnno.class)); // true System.out.println(AnnotatedElementUtils.isAnnotated(Child.class, RequestMapping.class)); //true }
- 关于getMerge之类的方法,在后面讲
@AliasFor
的时候再详说吧
AnnotationBeanUtils:拷贝注解值到指定的Bean中
它在org.springframework.beans.annotation
包下,并且这个包下只有它一个类。该类只有一个核心方法。
public abstract class AnnotationBeanUtils { // excludedProperties 排除的属性值不拷贝 public static void copyPropertiesToBean(Annotation ann, Object bean, String... excludedProperties) { copyPropertiesToBean(ann, bean, null, excludedProperties); } public static void copyPropertiesToBean(Annotation ann, Object bean, @Nullable StringValueResolver valueResolver, String... excludedProperties) { // 用set去重 Set<String> excluded = new HashSet<>(Arrays.asList(excludedProperties)); // 这是拿到该注解的所有属性(编译后都是通过method的方式存储的) Method[] annotationProperties = ann.annotationType().getDeclaredMethods(); // 吧这个Bean包装成一个BeanWrapper BeanWrapper bw = PropertyAccessorFactory.forBeanPropertyAccess(bean); for (Method annotationProperty : annotationProperties) { String propertyName = annotationProperty.getName(); if (!excluded.contains(propertyName) && bw.isWritableProperty(propertyName)) { // 拿到注解的值 Object value = ReflectionUtils.invokeMethod(annotationProperty, ann); // 若是字符串类型,还可以处理(也就值支持到了{}这种占位符形式) if (valueResolver != null && value instanceof String) { value = valueResolver.resolveStringValue((String) value); } // 把该Value值设置进去 bw.setPropertyValue(propertyName, value); } } } }
备注:这个我们一般用不着,Spring内在JMX相关类中使用。比如AnnotationJmxAttributeSource
AnnotationConfigUtils:(重要),和Config配置类有关的注解工具类
AnnotationConfigUtils是一个Spring内部工具类,用于识别注解配置类中的bean定义。(和Bean注册有关)
public class AnnotationConfigUtils { // 这个常量在我们AnnotationConfigApplicationContext#setBeanNameGenerator的时候会执行这么一句话: //getBeanFactory().registerSingleton(AnnotationConfigUtils.CONFIGURATION_BEAN_NAME_GENERATOR, beanNameGenerator) // 然后在处理@Configuration里的@Bean的时候,会get出来处理名字 public static final String CONFIGURATION_BEAN_NAME_GENERATOR = "org.springframework.context.annotation.internalConfigurationBeanNameGenerator"; //============= Spring默认会注册进去的7个Bean(若没导包,有可能是5个哦) =========================== public static final String CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME = "org.springframework.context.annotation.internalConfigurationAnnotationProcessor"; public static final String AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME = "org.springframework.context.annotation.internalAutowiredAnnotationProcessor"; public static final String REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME = "org.springframework.context.annotation.internalRequiredAnnotationProcessor"; public static final String COMMON_ANNOTATION_PROCESSOR_BEAN_NAME = "org.springframework.context.annotation.internalCommonAnnotationProcessor"; public static final String PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME = "org.springframework.context.annotation.internalPersistenceAnnotationProcessor"; public static final String EVENT_LISTENER_PROCESSOR_BEAN_NAME = "org.springframework.context.event.internalEventListenerProcessor"; public static final String EVENT_LISTENER_FACTORY_BEAN_NAME = "org.springframework.context.event.internalEventListenerFactory"; private static final String PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME = "org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor"; private static final boolean jsr250Present = ClassUtils.isPresent("javax.annotation.Resource", AnnotationConfigUtils.class.getClassLoader()); private static final boolean jpaPresent = ClassUtils.isPresent("javax.persistence.EntityManagerFactory", AnnotationConfigUtils.class.getClassLoader()) && ClassUtils.isPresent(PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME, AnnotationConfigUtils.class.getClassLoader()); }
- public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(BeanDefinitionRegistry registry, @Nullable Object source):该方法主要是向容器注册了一组基础设施PostProcessor bean定义,这些bean定义生成的PostProcessor实例被框架自己用于识别注解配置类中的bean定义(就是我们上面说的7大默认Bean定义,role均为:BeanDefinition.ROLE_INFRASTRUCTURE表示框架自己用的)。 它还为Bean工厂设置了:setDependencyComparator和setAutowireCandidateResolver
- public static void processCommonDefinitionAnnotations(AnnotatedBeanDefinition abd):处理通用的Bean定义上的注解,该方法从原始bean定义的元数据中获取那些通用的注解信息:@Lazy,@DependsOn,@Role,@Description,然后设置AnnotatedBeanDefinition实例相应的属性
基本上这个工具类是Spring内部使用的,我们用不着。它在org.springframework.context.annotation包内
ConfigurationClassUtils:Spring内部处理@Configuration的工具类
这个工具类只处理@Configuration配置类的。是Full模式还是Lite模式
public static boolean isFullConfigurationCandidate(AnnotationMetadata metadata) { return metadata.isAnnotated(Configuration.class.getName()); } public static boolean isLiteConfigurationCandidate(AnnotationMetadata metadata){ //有@Component、@Component、@Import、@ImportResource标注的 // 或者类内部有@Bean标注的方法 都属于Lite模式的配置类 ... } public static boolean isConfigurationCandidate(AnnotationMetadata metadata) { return (isFullConfigurationCandidate(metadata) || isLiteConfigurationCandidate(metadata)); } / public static boolean isFullConfigurationClass(BeanDefinition beanDef) { return CONFIGURATION_CLASS_FULL.equals(beanDef.getAttribute(CONFIGURATION_CLASS_ATTRIBUTE)); } public static boolean isLiteConfigurationClass(BeanDefinition beanDef) { return CONFIGURATION_CLASS_LITE.equals(beanDef.getAttribute(CONFIGURATION_CLASS_ATTRIBUTE)); } // 获取@Order的值 since Spring5.0 @Nullable public static Integer getOrder(AnnotationMetadata metadata) { Map<String, Object> orderAttributes = metadata.getAnnotationAttributes(Order.class.getName()); return (orderAttributes != null ? ((Integer) orderAttributes.get(AnnotationUtils.VALUE)) : null); } // since Spring4.2 public static int getOrder(BeanDefinition beanDef) { Integer order = (Integer) beanDef.getAttribute(ORDER_ATTRIBUTE); return (order != null ? order : Ordered.LOWEST_PRECEDENCE); }
OrderUtils:处理@Order和javax.annotation.Priority
public abstract class OrderUtils { @Nullable public static Integer getOrder(Class<?> type) { Order order = AnnotationUtils.findAnnotation(type, Order.class); if (order != null) { return order.value(); } // 兼容到了JDK6提供的javax.annotation.Priority这个注解(需要额外导包) Integer priorityOrder = getPriority(type); if (priorityOrder != null) { return priorityOrder; } return null; } @Nullable public static Integer getPriority(Class<?> type) { if (priorityAnnotationType != null) { Annotation priority = AnnotationUtils.findAnnotation(type, priorityAnnotationType); if (priority != null) { return (Integer) AnnotationUtils.getValue(priority); } } return null; } // 最常调用的还是下列方法: public static int getOrder(Class<?> type, int defaultOrder) { Integer order = getOrder(type); return (order != null ? order : defaultOrder); } @Nullable public static Integer getOrder(Class<?> type, @Nullable Integer defaultOrder) { Integer order = getOrder(type); return (order != null ? order : defaultOrder); } }