首页 > 其他分享 >@ComponentScan注解 -【Spring底层原理

@ComponentScan注解 -【Spring底层原理

时间:2024-04-01 23:00:38浏览次数:25  
标签:Spring 扫描 value ComponentScan Filter 注解 class

案例已上传GitHub,欢迎star:https://github.com/oneStarLR/spring-annotation

一、注解用法


1. 背景知识

什么是组件?

组件也是抽象的概念,可以理解为一些符合某种规范的类组合在一起就构成了组件,他可以提供某些特定的功能,但实际他们都是类,只不过有他们特殊的规定。组件和类的关系:符合某种规范的类的组合构成组件。

2. @ComponentScan注解作用

1. 将组件自动加载到容器

加了包扫描@ComponentScan注解后,只要标注了@Controller、@Service、@Repository、@Component注解中的任何一个,其组件都会被自动扫描,加入到容器中。

2. 通过属性指定扫描

【1】value:指定要扫描的包

【2】excludeFilters=Filter[ ]:设置排除的过滤条件,指定扫描的时候按照什么规则排除哪些组件,不扫描哪些包

【3】includeFilters=filter[ ]:设置扫描过滤条件,指定扫描的时候按照什么规则包含哪些组件,满足该条件才进行扫描

【4】自定义过滤规则:通过实现TypeFilter接口,自定义过滤规则

下面咱们通过实例来分析一下@ComponentScan注解的作用

二、实例分析


以maven项目为例,通过@ComponentScan、@Controller、@Service、@Repository注解获取容器中的对象:

// 启动类

@Test

public void TestMain(){

AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);

String[] beanNames = applicationContext.getBeanDefinitionNames();

for(String beanName : beanNames){

System.out.println(“容器中对象名称:”+beanName);

}

}

// 配置类

@Configuration

@ComponentScan(value = “com.onestar”)

public class AppConfig {

}

// 控制层

@Controller

public class UserController {

}

// 业务层

@Service

public class UserService {

}

// 持久层

@Repository

public class UserDao {

}

运行测试类,可以看到如下打印信息,除了spring启动时注入到容器的对象外,还有我们自己加了注解,被spring扫描,加入到容器中

  • @ComponentScan(value = "com.onestar"):value表示指定要扫描的包

image-20210120110132056

点进@ComponentScan注解源码,我们可以看到,使用value可以指定要扫描的包,我们还可以排除要扫描的包,包含要扫描的包,甚至还可以自定义过滤规则

  • excludeFilters=Filter[ ]:指定扫描的时候按照什么规则排除哪些包

  • includeFilters=filter[ ]:指定扫描的时候是需要包含哪些包

【@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 {};

/**

* 命名注册的Bean,可以自定义实现命名Bean,

* 1、@ComponentScan(value = “spring.annotation.componentscan”,nameGenerator = MyBeanNameGenerator.class)

* MyBeanNameGenerator.class 需要实现 BeanNameGenerator 接口,所有实现BeanNameGenerator 接口的实现类都会被调用

* 2、使用 AnnotationConfigApplicationContext 的 setBeanNameGenerator方法注入一个BeanNameGenerator

* BeanNameGenerator beanNameGenerator = (definition,registry)-> String.valueOf(new Random().nextInt(1000));

* AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext();

* annotationConfigApplicationContext.setBeanNameGenerator(beanNameGenerator);

* annotationConfigApplicationContext.register(MainConfig2.class);

* annotationConfigApplicationContext.refresh();

* 第一种方式只会重命名@ComponentScan扫描到的注解类

* 第二种只有是初始化的注解类就会被重命名

* 列如第一种方式不会重命名 @Configuration 注解的bean名称,而第二种就会重命名 @Configuration 注解的Bean名称

*/

Class<? extends BeanNameGenerator> nameGenerator() default BeanNameGenerator.class;

/**

* 用于解析@Scope注解,可通过 AnnotationConfigApplicationContext 的 setScopeMetadataResolver 方法重新设定处理类

* ScopeMetadataResolver scopeMetadataResolver = definition -> new ScopeMetadata();  这里只是new了一个对象作为演示,没有做实际的逻辑操作

* AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext();

* annotationConfigApplicationContext.setScopeMetadataResolver(scopeMetadataResolver);

* annotationConfigApplicationContext.register(MainConfig2.class);

* annotationConfigApplicationContext.refresh();

* 也可以通过@ComponentScan 的 scopeResolver 属性设置

*@ComponentScan(value = “spring.annotation.componentscan”,scopeResolver = MyAnnotationScopeMetadataResolver.class)

*/

Class<? extends ScopeMetadataResolver> scopeResolver() default AnnotationScopeMetadataResolver.class;

// 设置类的代理模式

ScopedProxyMode scopedProxy() default ScopedProxyMode.DEFAULT;

/**

* 扫描路径 如 resourcePattern = “**/*.class”

* 使用  includeFilters 和 excludeFilters 会更灵活

*/

String resourcePattern() default “**/*.class”;

/**

* 指示是否应启用对带有{@code @Component},{@ code @Repository},

* {@ code @Service}或{@code @Controller}注释的类的自动检测。

*/

boolean useDefaultFilters() default true;

/**

* 对被扫描的包或类进行过滤,若符合条件,不论组件上是否有注解,Bean对象都将被创建

* @ComponentScan(value = “com.onestar”,includeFilters = {

*     @ComponentScan.Filter(type = FilterType.ANNOTATION, classes = {Controller.class, Service.class}),

*     @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = {UserDao.class}),

*     @ComponentScan.Filter(type = FilterType.CUSTOM, classes = {MyTypeFilter.class}),

*     @ComponentScan.Filter(type = FilterType.ASPECTJ, pattern = “spring.annotation…*”),

*     @ComponentScan.Filter(type = FilterType.REGEX, pattern = “1+Dao$”)

* },useDefaultFilters = false)

* useDefaultFilters 必须设为 false

*/

ComponentScan.Filter[] includeFilters() default {};

// 设置排除的过滤条件,指定扫描的时候按照什么规则排除哪些组件,排除要扫描的包,用法参考includeFilters

ComponentScan.Filter[] excludeFilters() default {};

/**

* 指定是否应注册扫描的Bean以进行延迟初始化。

* @ComponentScan(value = “com.onestar”,lazyInit = true)

*/

boolean lazyInit() default false;

// @Filter注解,用于 includeFilters 或 excludeFilters 的类型筛选器

@Retention(RetentionPolicy.RUNTIME)

@Target({})

public @interface Filter {

/**

* 要使用的过滤器类型,默认为 ANNOTATION 注解类型

* @ComponentScan.Filter(type = FilterType.ANNOTATION, classes = {Controller.class, Service.class})

*/

FilterType type() default FilterType.ANNOTATION;

/**

* 过滤器的参数,参数必须为class数组,单个参数可以不加大括号

* 只能用于 ANNOTATION 、ASSIGNABLE_TYPE 、CUSTOM 这三个类型

* @ComponentScan.Filter(type = FilterType.ANNOTATION, value = {Controller.class, Service.class})

* @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = {UserDao.class})

* @ComponentScan.Filter(type = FilterType.CUSTOM, classes = {MyTypeFilter.class})

*/

@AliasFor(“classes”)

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

/**

* 作用同上面的 value 相同

* ANNOTATION 参数为注解类,如  Controller.class, Service.class, Repository.class

* ASSIGNABLE_TYPE 参数为类,如 UserDao.class

* CUSTOM  参数为实现 TypeFilter 接口的类 ,如 MyTypeFilter.class

* MyTypeFilter 同时还能实现 EnvironmentAware,BeanFactoryAware,BeanClassLoaderAware,ResourceLoaderAware

* 这四个接口

* EnvironmentAware

* 此方法用来接收 Environment 数据 ,主要为程序的运行环境,Environment 接口继承自 PropertyResolver 接口,

* 详细内容在下方

* @Override

* public void setEnvironment(Environment environment) {

*    String property = environment.getProperty(“os.name”);

* }

*

* BeanFactoryAware

* BeanFactory Bean容器的根接口,用于操作容器,如获取bean的别名、类型、实例、是否单例的数据

* @Override

* public void setBeanFactory(BeanFactory beanFactory) throws BeansException {

*     Object bean = beanFactory.getBean(“BeanName”)

* }

*

* BeanClassLoaderAware

* ClassLoader 是类加载器,在此方法里只能获取资源和设置加载器状态

* @Override

* public void setBeanClassLoader(ClassLoader classLoader) {
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Java工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注Java获取)

img

最后总结

ActiveMQ+Kafka+RabbitMQ学习笔记PDF

image.png

  • RabbitMQ实战指南

image.png

  • 手写RocketMQ笔记

image.png

  • 手写“Kafka笔记”

image

关于分布式,限流+缓存+缓存,这三大技术(包含:ZooKeeper+Nginx+MongoDB+memcached+Redis+ActiveMQ+Kafka+RabbitMQ)等等。这些相关的面试也好,还有手写以及学习的笔记PDF,都是啃透分布式技术必不可少的宝藏。以上的每一个专题每一个小分类都有相关的介绍,并且小编也已经将其整理成PDF啦
《一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码》点击传送门即可获取!
Q实战指南

[外链图片转存中…(img-l8PZc8GO-1711959311276)]

  • 手写RocketMQ笔记

[外链图片转存中…(img-HS4Xg7y9-1711959311276)]

  • 手写“Kafka笔记”

[外链图片转存中…(img-6GBAf9Vo-1711959311276)]

关于分布式,限流+缓存+缓存,这三大技术(包含:ZooKeeper+Nginx+MongoDB+memcached+Redis+ActiveMQ+Kafka+RabbitMQ)等等。这些相关的面试也好,还有手写以及学习的笔记PDF,都是啃透分布式技术必不可少的宝藏。以上的每一个专题每一个小分类都有相关的介绍,并且小编也已经将其整理成PDF啦
《一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码》点击传送门即可获取!


  1. A-Za-z. ↩︎

标签:Spring,扫描,value,ComponentScan,Filter,注解,class
From: https://blog.csdn.net/a369966697/article/details/137237266

相关文章

  • 【异常】Spring的依赖注入(DI)系统提示异常,因为漏了一个实现类导致了错误Parameter 0 of
    一、异常内容2024-04-0111:44:39.912[main]ERRORorg.springframework.boot.diagnostics.LoggingFailureAnalysisReporter-***************************APPLICATIONFAILEDTOSTART***************************Description:Parameter0ofconstructorinc......
  • IDEA中新建SpringBoot模块,JDK版本问题解决
    问题描述IDEA中新建SpringBoot模块,使用的JAVAJDK1.8,新建模块时选项中没有JDK8: 运行时报错,JDK之类的问题解决方案,查看修改以下四个地方:(1)设置-Java编译器 (2)项目结构--依赖以及源码 ......
  • 10.Mybatis在springboot中的整合总结
    如果你是从事java开发的那数据库绝对是你离不开的东西我以mysql为例好像都是用的这个吧下载就不多bb了直接看springboot整合添加依赖jdbcmysql和mybatis的依赖然后千万别去当当敲代码了你做一步一个验证一步测试一下是否成功加载成功了properties(或者yaml)中配......
  • spring boot 3.2.x 踩坑
    1、factoryBeanObjectTypespringboot3.2.2+mybatis-plus-boot-starter3.5.5。定义了Mapper、继承com.baomidou.mybatisplus.extension.service.IService的接口、实现 com.baomidou.mybatisplus.extension.service.impl.ServiceImpl的类后,启动失败。异常信息如下:......
  • 基于Spring Cloud + Spring Boot的企业电子招标采购系统源码
    随着企业的快速发展,招采管理逐渐成为企业运营中的重要环节。为了满足公司对内部招采管理提升的要求,建立一个公平、公开、公正的采购环境至关重要。在这个背景下,我们开发了一款电子招标采购软件,以最大限度地控制采购成本,提高招投标工作的公开性和透明性,并确保符合国家电子招投标......
  • Java版商城:Spring Cloud+SpringBoot b2b2c电子商务平台,多商家入驻、直播带货及免 费
    随着互联网的快速发展,越来越多的企业开始注重数字化转型,以提升自身的竞争力和运营效率。在这个背景下,鸿鹄云商SAAS云产品应运而生,为企业提供了一种简单、高效、安全的数字化解决方案。鸿鹄云商SAAS云产品是一种基于云计算的软件服务,旨在帮助企业实现业务流程的自动化和优化。......
  • 【NoSQL】SpringBoot+Redis简单使用
    【NoSQL】SpringBoot+Redis简单使用Redis是一款key-value存储结构的内存级NoSQL数据库;支持多种数据存储格式、支持持久化、支持集群windows下载:https://github.com/tporadowski/redis/releases<dependency><groupId>org.springframework.boot</groupId><artifactId......
  • SpringBoot集成MyBatis-Plus快速入门Demo
    目录1.MyBatis-Plus概述2.MyBatis-Plus框架结构3. MyBatis-Plus快速入门3.1 创建表3.2 创建工程3.3 导入依赖3.4添加配置文件application.yml,配置数据库信息3.5 创建实体类(包括自动填充)3.6创建配置类(包括配置乐观锁、分页、逻辑删除等插件) 3.7编写自动填......
  • 地方废物回收机构管理的设计与实现|Springboot+ Mysql+Java+ B/S结构(可运行源码+数据
    本项目包含可运行源码+数据库+LW,文末可获取本项目的所有资料。推荐阅读100套最新项目持续更新中.....2024年计算机毕业论文(设计)学生选题参考合集推荐收藏(包含Springboot、jsp、ssm+vue等技术项目合集)目录1.管理员功能效果图2.员工功能3.系统功能设计4.数据库E-R图设......
  • 基于vue的MOBA类游戏攻略分享平台的设计与实现|Springboot+Vue+ Mysql+Java+ B/S结构(
    本项目包含可运行源码+数据库+LW,文末可获取本项目的所有资料。现今,越来越多的人乐于选择一项合适的管理方案,但是普通用户往往受到管理经验地限制,这时MOBA类游戏攻略分享平台的崛起,大量游戏攻略进入人们生活,而MOBA类游戏攻略制无疑是游戏攻略管理的最好制度,在这样成功的管理模......