spring core:@Component的派生性 - Go语言中文社区

spring core:@Component的派生性


spring对注解的拓展,早已超越J2EE的规约。通过注解可以实现其派生性(Annotation Hierarchy)。自从spring2.5开始,每个大版本都对其进行了增强。

何为派生?

没错一般能想到的就是属性派生,直接上代码,其实ParentChild看似是派生的关系,但实则并无关系!

它们是两个毫无关联的接口(我在面试的时候会提问:注解和接口的关系),通过javap -v .Child.class便可得知

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public  @interface Parent {
    String name() default "a";
}
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Parent
public @interface Child {
    String name() default "b";
}
@Child
class Home { }
@Test
public void metaTest() {
    Annotation[] annotations = Home.class.getDeclaredAnnotations();
    System.out.println(Arrays.toString(annotations));//[@com.yh.lucky.day.service.Child(name=Jack)]
    annotations = annotations[0].annotationType().getDeclaredAnnotations();
    System.out.println(Arrays.toString(annotations));//[@java.lang.annotation.Target(value=[TYPE]), @java.lang.annotation.Retention(value=RUNTIME), @java.lang.annotation.Documented(), @com.yh.lucky.day.service.Parent(name=John)]
}

那派生就不是真正意义上的派生(Override),而spring对其加以拓展,将其界定在层次性:

@Parent
	@Child

也就是说,有层次结构的注解,spring就认定是具备派生性(extends),并且派生性强调的类型(Child extends Parent)。

Component

在spring中有很多*@Repository,@Service,@Controller,@Configuration等*均派生于@Component,这也就是为什么你添加了一个注解(只需要标记为@Component),而不用改动spring core。

  • Spring2.5 仅支持单层次的@Component派生,未采用层次递归获取Annotation[]
  • Spring3.x 实现仅两层@Component派生
  • Spring4.x开始采用递归方式查找元注解
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface HignLevelAnnotation {
    String value() default "a";
}
@HignLevelAnnotation
public class TestComponent {//此时可以自动注入到spring ioc中
}
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@HignLevelAnnotation
public @interface MiddleLevelAnnotation {
    String value() default "b";
}
@MiddleLevelAnnotation
public class TestComponent {//此时还可以自动注入到spring ioc中
}
@Test
public void metaTest() throws IOException {
    CachingMetadataReaderFactory readerFactory = new CachingMetadataReaderFactory();
    //ResourcePatternUtils
    Resource resource = new ClassPathResource("TestComponent.class",TestComponent.class);
    AnnotationMetadata asmVisitor = readerFactory.getMetadataReader(resource).getAnnotationMetadata();
    //AnnotationMetadataReadingVisitor#attributesMap内部存储了注解记录
    System.out.println(((AnnotationMetadataReadingVisitor)asmVisitor).isAnnotated("org.springframework.stereotype.Component"));
    //上面的Asm可能难懂,那下面反射的更易懂
    Component cp = AnnotationUtils.findAnnotation(TestComponent.class, Component.class);
    System.out.println(cp.value());
    HignLevelAnnotation cp2 = AnnotationUtils.findAnnotation(TestComponent.class, HignLevelAnnotation.class);
    System.out.println(cp2.value());    
}

原理-AnnotationMetadataReadingVisitor

之前的章节讲过MetadataReaderFactory,读取类或者注解相关信息有两种方式:反射和ASM。

  • ClassMetadata,类元信息抽象,StandardClassMetadata(反射),ClassReader(ASM)
  • MethodMetadata,方法元信息抽象,StandardMethodMetadata(反射),MethodMetadataReadingVisitor(ASM)
  • AnnotationMetadata,注解元信息抽象,StandardAnnotationMetadata(反射),AnnotationMetadataReadingVisitor(ASM)
  • AnnotationAttributes,注解属性抽象
  • MetadataReader,元信息读取抽象,通过MetadataReaderFactory获取

而``AnnotationMetadataReadingVisitor的内部实现使用AnnotationAttributesReadingVisitor`类来递归的查找元注解。反射的API类`AnnotationUtils`易用性则更强。

那要满足真正意义上的派生,不仅仅时类型,spring为此开发了@AliasFor

版权声明:本文来源CSDN,感谢博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/itsoftchenfei/article/details/103783052
站方申明:本站部分内容来自社区用户分享,若涉及侵权,请联系站方删除。
  • 发表于 2020-02-25 00:30:46
  • 阅读 ( 1108 )
  • 分类:

0 条评论

请先 登录 后评论

官方社群

GO教程

猜你喜欢