@ComponentScan注解原理

本文深入探讨了Spring框架中@ComponentScan注解的原理,首先解释了@Component的作用,并通过创建自定义注解和测试类展示了其工作方式。接着,文章进入了源码层面,详细分析了Spring如何扫描和注册带有@Component注解的类,包括ClassPathBeanDefinitionScanner和ClassPathScanningCandidateComponentProvider等关键类的作用。最后,文章揭示了如何通过ASM库访问类元数据,并指出@ComponentScan注解的匹配逻辑。
摘要由CSDN通过智能技术生成

ComponentScan源码解析

下文源码分析版本Spring 5.2.5 release

理解@Component

@Component作为一种由Spring容器托管的通用组件,任何被@Component标注的组件均为组件扫描的对象。
类似的组件比如@Repository@Service或者使用@Component注解作为自定义注释。

//@see org.springframework.context.annotation.ClassPathBeanDefinitionScanner
@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 "";

}

1. 利用@Repository自定义一个注解

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
//@Component
@Repository
public @interface StringRepository {

    String value() default "";
}

2. 写一个测试类NameRepository,加上该注解

@StringRepository("chineseNameRepository")
public class NameRepository {

    public List<String> findAll() {
        return Arrays.asList("张三", "李四", "王二麻子");
    }
}

3. 测试NameRepository类是否能被Spring容器加载

创建一个测试类ComponentBootStrap,代码如下

@Configuration
@ComponentScan
public class ComponentBootStrap {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ComponentBootStrap.class);
//        context.register(ComponentBootStrap.class);
//        context.refresh();
        NameRepository nameRepository = context.getBean(NameRepository.class);
        System.out.println("nameRepository.findAll() = " + nameRepository.findAll());
    }
}

小提示:类NameRepository与引导类ComponentBootStrap需放到一个包下,才能被@ComponentScan扫描加载。
输出结果为:nameRepository.findAll() = [张三, 李四, 王二麻子],这说明了自定义注解类@StringRepository也有类似于@Component的功能。
结论:只要你注解中包含了@Component,就能被Spring容器托管。因为@Component是元注解,也可以联合元注解去创造组合注解,比如@RestController就是由@Controller@ResponseBody组成的。
官网beans-meta-annotations

上面例子来源于小马哥的《Spring Boot编程思想》,NameRepository注解不是继承@ComponentScan,但是效果却是继承,借用小马哥对这种模式注解的定义为@ComponentScan的派生性。那下文就探索一下@ComponentScan派生性的原理。

探索源码

只要注解里面含有@Component,就会被Spring扫描,并注册。为什么会这么呢?是不是跟扫描方式有关系呢?
Spring扫描bean的方式有两种,一种是自定义标签<context:component-scan base-package=“com.xxx”/>这里base-package值填写NameRepository的包名,一种是注解@ComponentScan,如果不填写value值,就默认扫描注解类的包下所有类。

第一种自定义标签的方式这里暂时不讨论,以后会专门写一篇来解析。
我们这里重点讲解注解@ComponentScan方式。

1. 先看@ComponentScan源码

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@Repeatable(ComponentScans.class)
public @interface ComponentScan {

	@AliasFor("basePackages")
	String[] value() default {};

	@AliasFor("value")
	String[] basePackages() default {};

	Class<?>[] basePackageClasses() default {};

	Class<? extends BeanNameGenerator> nameGenerator() default BeanNameGenerator.cl
  • 4
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值