当前位置: 首页 > news >正文

Spring之@ComponentScan注解

1. @ComponentScan 注解可配置属性

  • value
  • basePackages
  • basePackageClasses
  • nameGenerator
  • scopeResolver
  • scopedProxy
  • resourcePattern
  • useDefaultFilters
  • includeFilters
  • excludeFilters
  • lazyInit

2. 相关属性的作用

2.1  代码准备

2.1.1 创建配置类 A、B、C
@Component
public class A {
}@Component
public class B {
}@Component
public class C {
}
2.1.2 创建配置类 AppConfig
@ComponentScan
public class AppConfig {
}
2.1.3 创建启动类 Main
public class Main {public static void main(String[] args) {AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);}
}
2.1.4 工程文件结构

2.2 value、basePackages、basePackageClasses

@ComponentScan 注解扫描的 packages

  • 配置类是否指定value、basePackages、basePackageClasses
      • value、basePackages 指定的 packages
      • basePackageClasses 指定 classes 所在的 packages
      • 扫描该配置类所在的 package
2.2.1 Spring 内置 bean 的数量 

内置 14 个

PS:其中有一个自定义的 bean(AppConfig),这里为了方便说明,把它当成内置的

2.2.2 扫描 com.ys.p1
2.2.2.1 修改配置类 AppConfig
@ComponentScan("com.ys.p1")
public class AppConfig {
}
2.2.2.2 运行 Main 方法,查看运行结果

一共 15 个 beans  = 内置(14) + p1(1)

2.2.3 扫描 com.ys.p1、com.ys.p2 及 basePackageClasses 属性设置
2.2.3.1 修改配置类 AppConfig
@ComponentScan(value = {"com.ys.p1", "com.ys.p2"}, basePackageClasses = C.class)
public class AppConfig {
}
2.2.3.2 运行 Main 方法,查看运行结果

一共 17 个 beans  = 内置(14) + p1(1) + p2(1) + p3(1)

2.3 nameGenerator

beanName 生成器,默认情况下为类名的驼峰形式

2.3.1 默认情况下的 beanNames

2.3.1 自定义 nameGenerator
2.3.1.1 自定义BeanNameGenerator(MyBeanNameGenerator)
public class MyBeanNameGenerator extends AnnotationBeanNameGenerator {@Overridepublic String generateBeanName(BeanDefinition definition, BeanDefinitionRegistry registry) {String beanName = super.generateBeanName(definition, registry);return "my" + beanName;}
}
2.3.1.2 修改配置类 AppConfig
@ComponentScan(value = "com.ys", nameGenerator = MyBeanNameGenerator.class)
public class AppConfig {
}
2.3.1.3 运行 Main 方法,查看运行结果

2.4 scopedProxy

动态代理方式,需要和 @Scope 注解配合使用

  • @Scope 是否指定 proxyMode
      • INTERFACES:对 bean 进行 jdk 动态代理
      • TARGET_CLASS​​​​:对 bean 进行 cglib 动态代理
      • NO:不进行动态代理
      • @Scope 是否指定 proxyMode
          • INTERFACES:对 bean 进行 jdk 动态代理
          • TARGET_CLASS​​​​:对 bean 进行 cglib 动态代理
          • NO:不进行动态代理
          • 不进行动态代理
2.4.1 scopedProxy 功能演示
2.4.1.1 给实体类 A 添加 @Scope 注解
@Component
@Scope
public class A {}
2.4.1.2 修改配置类 AppConfig
@ComponentScan(value = "com.ys", scopedProxy = ScopedProxyMode.INTERFACES)
public class AppConfig {
}
 2.4.1.3 运行 Main 方法,查看运行结果(1)

通过运行结果,得出结论:a 是一个 jdk 代理对象

2.4.1.4 修改配置类 AppConfig(将 scopedProxy 改为 TARGET_CLASS
@ComponentScan(value = "com.ys", scopedProxy = ScopedProxyMode.TARGET_CLASS)
public class AppConfig {
}
 2.4.1.5 运行 Main 方法,查看运行结果(2) 

通过运行结果,得出结论:a 是一个 cglib 代理对象

2.4.1.6 将实体类 A 的 @Scope 注解的 scopedProxy 属性设置为 INTERFACES
@Component
@Scope(proxyMode = ScopedProxyMode.INTERFACES)
public class A {}
2.4.1.7 运行 Main 方法,查看运行结果(3) 

通过运行结果,得出结论:a 是一个 jdk 代理对象,即 @Scope 注解设置的值优先级高于 @ComponentScan 注解设置的值 

2.5 scopeResolver

动态代理处理器,如果配置了 scopedProxy,则 scopeResolver 无效

2.5.1 自定义 scopeResolver 手动处理代理逻辑,让扫描的路径都进行 jdk 动态代理
2.5.1.1 自定义scopeResolver JdkScopeMetadataResolver
public class JdkScopeMetadataResolver implements ScopeMetadataResolver {@Overridepublic ScopeMetadata resolveScopeMetadata(BeanDefinition definition) {ScopeMetadata scopeMetadata = new ScopeMetadata();scopeMetadata.setScopedProxyMode(ScopedProxyMode.INTERFACES);return scopeMetadata;}
}
2.5.1.2 修改配置类 AppConfig
@ComponentScan(value = "com.ys", scopeResolver = JdkScopeMetadataResolver.class)
public class AppConfig {
}
2.5.1.3 运行 Main 方法,查看运行结果

通过运行结果,得出结论:扫描的路径的 bean 都被 jdk 动态代理

2.6 resourcePattern

@ComponentScan 注解扫描的资源,需要和 resourcePattern 相匹配,默认值:**/*.class

2.6.1 演示 resourcePattern 作用
2.6.1.1 修改配置类 AppConfig
@ComponentScan(value = "com.ys", resourcePattern = "p1/*.class")
public class AppConfig {
}
2.6.1.2 运行 Main 方法,查看运行结果

通过运行结果,得出结论:只有 p1 文件夹下的实体类 A 才符合条件,所以只存在 a,不存在 b

2.7 useDefaultFilters

默认情况下,如果类上存在 @Component@ManagedBean@Named 注解,则会被扫描、解析成 beanDefinition,进而被实例化成 bean。如果值设为 false,即使存在 @Component@ManagedBean@Named 注解,也不会被扫描、解析、实例化成 bean

2.7.1 演示 useDefaultFilters 作用
2.7.1.1 修改配置类 AppConfig
@ComponentScan(value = "com.ys", useDefaultFilters = false)
public class AppConfig {
}
2.7.1.2 运行 Main 方法,查看运行结果

通过运行结果,得出结论:即使实体类 A、B、C 类上存在 @Component 注解,也不会被扫描、解析、实例化成 bean

2.8 includeFilters

如果指定了 includeFilters 或 useDefaultFilters 为 true,只要满足任何一个 filter 的 match 方法,就会被扫描、解析、实例化成 bean

2.8.1 演示 includeFilters 作用
2.8.1.1 创建自定义注解 MyComponent
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
public @interface MyComponent {}
2.8.1.2 修改配置类 AppConfig
@ComponentScan(value = "com.ys", includeFilters = {@ComponentScan.Filter(type = FilterType.ANNOTATION, classes = MyComponent.class)})
public class AppConfig {
}
2.8.1.3 将实体类 C 类上的注解替换成 @MyComponent
@MyComponent
public class C {
}
2.8.1.4 运行 Main 方法,查看运行结果

通过运行结果,得出结论:自定义 includeFilters 生效

2.9 excludeFilters

excludeFilters 与 includeFilters 作用相反,不过 excludeFilters 的优先级更高,如果满足 excludeFilters 的 match 方法,则 useDefaultFilters 和 includeFilters 失效

2.10 lazyInit

是否懒加载,默认 false

2.10.1 演示 lazyInit 作用
2.10.1.1 修改配置类 AppConfig
@ComponentScan(value = "com.ys", includeFilters = {@ComponentScan.Filter(type = FilterType.ANNOTATION, classes = MyComponent.class)},lazyInit = true)
public class AppConfig {
}
2.10.1.2 运行 Main 方法,查看运行结果

 通过运行结果,得出结论:a 是懒加载的

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • HTTP/1.1
  • 【ACM独立出版丨接受全文摘要投稿】2024年生物医药和智能技术国际学术会议(ICBIT 2024,8月23-25)
  • Python知识点:如何使用Cocos2d进行游戏编程
  • 计算机网络 DNS HTTP HTTPS,缓存
  • HarmonyOS鸿蒙开发岗位面试中关于组件的问题总结
  • 【React】自定义右键菜单
  • 网站如何被Google收录?
  • Python | Leetcode Python题解之第328题奇偶链表
  • unity游戏开发003:深入理解Unity中的坐标系
  • windows与linux服务器之间通过scp快速并行的文件传输
  • 拒绝内卷:利用4P营销理论打造汇报PPT
  • JVM-运行数据区(堆、栈、元空间)
  • 黑神话悟空游戏攻略大全 黑神话悟空内存占用多少 国产3A级游戏《黑神话:悟空》评测代码已发 黑神话悟空测试画质130g MacBook可以玩黑神话悟空吗
  • C++:命名空间与输入输出
  • Go 1.21 新内置函数:min、max 和 clear
  • [js高手之路]搞清楚面向对象,必须要理解对象在创建过程中的内存表示
  • 【162天】黑马程序员27天视频学习笔记【Day02-上】
  • 03Go 类型总结
  • Angular Elements 及其运作原理
  • Druid 在有赞的实践
  • iOS 颜色设置看我就够了
  • iOS仿今日头条、壁纸应用、筛选分类、三方微博、颜色填充等源码
  • MobX
  • niucms就是以城市为分割单位,在上面 小区/乡村/同城论坛+58+团购
  • PHP CLI应用的调试原理
  • Promise面试题,控制异步流程
  • vue从创建到完整的饿了么(18)购物车详细信息的展示与删除
  • XForms - 更强大的Form
  • 工作中总结前端开发流程--vue项目
  • 基于Dubbo+ZooKeeper的分布式服务的实现
  • 前端存储 - localStorage
  • 前端设计模式
  • 如何优雅的使用vue+Dcloud(Hbuild)开发混合app
  • shell使用lftp连接ftp和sftp,并可以指定私钥
  • 仓管云——企业云erp功能有哪些?
  • ## 基础知识
  • $redis-setphp_redis Set命令,php操作Redis Set函数介绍
  • (10)工业界推荐系统-小红书推荐场景及内部实践【排序模型的特征】
  • (13)[Xamarin.Android] 不同分辨率下的图片使用概论
  • (3) cmake编译多个cpp文件
  • (c语言+数据结构链表)项目:贪吃蛇
  • (Matlab)遗传算法优化的BP神经网络实现回归预测
  • (保姆级教程)Mysql中索引、触发器、存储过程、存储函数的概念、作用,以及如何使用索引、存储过程,代码操作演示
  • (入门自用)--C++--抽象类--多态原理--虚表--1020
  • (循环依赖问题)学习spring的第九天
  • ******之网络***——物理***
  • .NET I/O 学习笔记:对文件和目录进行解压缩操作
  • .Net Memory Profiler的使用举例
  • .NET MVC、 WebAPI、 WebService【ws】、NVVM、WCF、Remoting
  • .Net mvc总结
  • .net 桌面开发 运行一阵子就自动关闭_聊城旋转门家用价格大约是多少,全自动旋转门,期待合作...
  • .NET6使用MiniExcel根据数据源横向导出头部标题及数据
  • .Net的C#语言取月份数值对应的MonthName值
  • .NET高级面试指南专题十一【 设计模式介绍,为什么要用设计模式】
  • .Net接口调试与案例