Spring中@Component注解是怎么实现的

电子说

1.3w人已加入

描述

概述

想必@Component注解大家一直在使用,只要类上加上它,就可以被Spring容器管理,那大家有想过它是怎么实现的吗?本篇文章就带领到家揭秘。

注解介绍

用来标记的类是一个“组件”或者说是一个Bean,Spring会自动扫描标记@Component注解的类作为一个Spring Bean对象。

注解源码:

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Indexed
public @interface Component {

 /**
  * The value may indicate a suggestion for a logical component name,
  * to be turned into a Spring bean in case of an autodetected component.
  * @return the suggested component name, if any (or empty String otherwise)
  */
 String value() default "";

}

属性说明:

  • value: 自定义当前组件或者说bean的名称,可以不配置, 不配置的话默认为组件的首字母小写的类名。

元注解说明:

  • 该注解只能使用在类,接口、枚举、其他注解上
  • 该注解的生命周期是运行时JVM
  • @Indexed元注解在spring 5.0引入,用于项目编译打包时,会在自动生成META-INF/spring.components文件,简历索引,从而提高组件扫描效率,减少应用启动时间。

注解使用

  1. 定义Person类,被@Component注解修饰

spring

  1. 检查Person类是否在扫描路径下

spring

  1. 获取bean验证

spring

spring

小结: 通过添加@Component能够将类转为Spring中的Bean对象,前提是能过够被扫描到。

原理解析

阅读源码,我们查看@Component注解的源码,从中可以看到一个关键的类ClassPathBeanDefinitionScanner,我们可以从这个类下手,找到切入点。

spring

分析ClassPathBeanDefinitionScanner类,找到核心方法doscan, 打个断点,了解整个调用链路。

spring

具体分析结果如下:

  1. SpringBoot应用启动会注册ConfigurationClassPostProcessor这个Bean,它实现了BeanDefinitionRegistryPostProcessor接口,而这个接口是Spring提供的一个扩展点,可以往BeanDefinition Registry中添加BeanDefintion。所以,只要能够扫描到@Component注解的类,并且把它注册到BeanDefinition Registry中即可。

spring

  1. 关键方法ConfigurationClassPostProcessorpostProcessBeanDefinitionRegistry,查找@Component的类,并进行注册。

spring

  1. 我们直接跳到是如何查找@Component的类的,核心方法就是ClassPathBeanDefinitionScanner#doScan
protected Set
  1. 重点关注ClassPathBeanDefinitionScanner#findCandidateComponents方法,找出候选的Bean Component
public Set
private Set
// 判断是否候选的Bean Component
protected boolean isCandidateComponent(MetadataReader metadataReader) throws IOException {
  // exclude过滤器,在exclude过滤其中的,会直接排除掉,返回false
        for (TypeFilter tf : this.excludeFilters) {
   if (tf.match(metadataReader, getMetadataReaderFactory())) {
    return false;
   }
  }
       // include过滤器, 这里会看到有AnnotationTypeFilter,注解类型过滤器
  for (TypeFilter tf : this.includeFilters) {
            // 调用AnnotationTypeFilter的match方法,来判断是否满足条件
   if (tf.match(metadataReader, getMetadataReaderFactory())) {
                // 下面在进行Condition的判断,就是类上的@Conditional,这里不是重点
    return isConditionMatch(metadataReader);
   }
  }
  return false;
 }

spring

而这个AnnotationTypeFilter默认是在构造函数中注册进去的。

spring

小结:

@ComponentSpring bean容器管理过程如下:

  1. 初始化时设置了Component类型过滤器;
  2. 根据指定扫描包扫描.class文件,生成Resource对象;
  3. 解析.class文件并注解归类,生成MetadataReader对象;
  4. 使用第一步的注解过滤器过滤出有@Component类;
  5. 生成BeanDefinition对象;
  6. BeanDefinition注册到Spring容器。

总结

经过这篇文章文章,是不是对@Component的使用和实现原理一清二楚了呢,其实Spring中还有@Service@Controller@Repository等注解,他们和@Component有什么区别呢,你知道吗?

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分