目录
Spring容器实现了对注解的增强扩展
包括:
注解的合成
注解的注解
统一的取数模型
注解的合成
我用一个案例说明演示一下:
我们自定义一个注解
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited//表示可以被注解
public @interface TestAnnotation {
@AliasFor("attribute")
String value() default "";
@AliasFor("value")
String attribute() default "";
}
写一个被TestAnnotation注解的类,并设置它的value = “test"
@TestAnnotation(value = "test")
public class AnnoDemo {
}
appTest:
/**
* 注解合并
* 对原注解的要求:
* 1、注解没有被合成过
* 2、不能是java类库的annotation(java.lang.annotation)
* 3、注解有属性方法, 且方法无入参,返回非void,且被aliasFor注解
*/
public static void annoMergeTest() {
TestAnnotation testAnnotation = AnnoDemo.class.getAnnotation(TestAnnotation.class);
// 合成注解
TestAnnotation synthesize = AnnotationUtils.synthesizeAnnotation(testAnnotation, null);
System.out.println("原来的注解的value = " + testAnnotation.value());
System.out.println("原来的注解的attribute = " + testAnnotation.attribute());
System.out.println("合成的注解的value = " + synthesize.value());
System.out.println("合成原来的注解的value = " + synthesize.attribute());
System.out.println("合成后的注解实现了TestAnnotation? " + (synthesize instanceof TestAnnotation));
System.out.println("合成后的注解实现了SynthesizedAnnotation? " + (synthesize instanceof SynthesizedAnnotation));
}
结果:
我们发现
当我们将value 和 attribute 设置 互为别名的时候。
使用原来的注解 。只能得到value的值,attribute是空的。
合成时候的注解,可以通过attribute 获取 value 的值。
使用AnnotationUtils.synthesizeAnnotation(testAnnotation, null) 对原来的注解进行合并之后其实返回的是一个被增强注解。它实现了原来的注解并且实现了SynthesizedAnnotation
注解的注解
Spring可以对注解进行增强,可以从注解上获得注解的注解(除了java自带的注解)。比如Spring的Configuration 被Component注解了,那么Spring认为被Configuration注解的类也是被Component了的。
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Configuration {
@AliasFor(annotation = Component.class)
String value() default "";
}
案例:
写一个被Configuration注解的类
@Configuration(value = "aaaa")
public class ConfigurationAnnoDemo {
}
Apptest:
/**
* 注解的注解
*/
public static void annoOfAnonoTest() {
Configuration configuration = ConfigurationAnnoDemo.class.getAnnotation(Configuration.class);
System.out.println("ConfigurationAnnoDemo被Configuration注解了吗" + (configuration != null));
Component component = ConfigurationAnnoDemo.class.getAnnotation(Component.class);
System.out.println("ConfigurationAnnoDemo被component注解了吗" + (component != null));
System.out.println("增强之后: ");
StandardAnnotationMetadata standardAnnotationMetadata = new StandardAnnotationMetadata(ConfigurationAnnoDemo.class);
//true
System.out.println("ConfigurationAnnoDemo拥有Configuration注吗? " + standardAnnotationMetadata.hasAnnotation(Configuration.class.getName()));
//false
System.out.println("ConfigurationAnnoDemo拥有Component注吗? " + standardAnnotationMetadata.hasAnnotation(Component.class.getName()));
//true
System.out.println("ConfigurationAnnoDemo被Configuration注解了吗? " + standardAnnotationMetadata.isAnnotated(Configuration.class.getName()));
//true
System.out.println("ConfigurationAnnoDemo被component注解了吗? " + standardAnnotationMetadata.isAnnotated(Component.class.getName()));
}
结果:
原来的Congiguration注解的类jdk是认为不被componet注解的。
用StandardAnnotationMetadata standardAnnotationMetadata = new StandardAnnotationMetadata(ConfigurationAnnoDemo.class);
进行增强后
Spring认为Congiguration注解的类是被componet注解的。
统一的取数模型
还是以Configuration作为案例。Spring对注解有一个统一的取数模型,它将注解和注解的注解上的属性名称和属性的值生成一个map,然后可以从map上获取所有属性的(name-> value)
/**
* 统一的annotation取数模型
*/
public static void unifiedAccessModelTest () {
StandardAnnotationMetadata standardAnnotationMetadata = new StandardAnnotationMetadata(ConfigurationAnnoDemo.class);
Map<String, Object> annotationAttributeMap = standardAnnotationMetadata.getAnnotationAttributes(Configuration.class.getName());
for (Map.Entry<String, Object> stringObjectEntry : annotationAttributeMap.entrySet()) {
System.out.println(stringObjectEntry.getKey() + " = " + stringObjectEntry.getValue());
}
annotationAttributeMap = standardAnnotationMetadata.getAnnotationAttributes(Component.class.getName());
for (Map.Entry<String, Object> stringObjectEntry : annotationAttributeMap.entrySet()) {
System.out.println(stringObjectEntry.getKey() + " = " + stringObjectEntry.getValue());
}
}
运行结果:
我们看到ConfigurationAnnoDemo上有注解Configuration,没有注解Component。但是Spring认为它也是被Component注解过的。并且可以获取到这些注解上的所有属性,用map管理。