Spring源码导读之对注解的扩展

Spring源码导读

目录

注解的合成

注解的注解

统一的取数模型


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管理。

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值