欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 新闻 > 焦点 > Spring之@ComponentScan注解

Spring之@ComponentScan注解

2025/7/3 10:17:24 来源:https://blog.csdn.net/qq_38257958/article/details/141165099  浏览:    关键词: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 是懒加载的

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词