上一个章节介绍了 @ComponentScan 注解的基础用法,该章节将详细介绍 @ComponentScan 注解每个属性的用法。@ComponentScan注解支持如下属性:
basePackages() 的类型安全替代方案,用于指定要扫描的组件以扫描带注释的组件。实例:
@ComponentScan(basePackageClasses = { IndexController.class, DateController.class })
上面实例将扫描 com.huangx.springboot.controller 和 com.huangx.springboot.controller2 包以及子包。
用于扫描带注解的组件的基本包。实例:
@ComponentScan(basePackages = { "com.huangx.springboot.controller", "com.huangx.springboot.controller2" }) @ComponentScan({ "com.huangx.springboot.controller", "com.huangx.springboot.controller2" })
上面实例将扫描 com.huangx.springboot.controller 和 com.huangx.springboot.controller2 包以及子包。
basePackages() 别名。实例见 basePackages
指定哪些类型不符合组件扫描的条件。实例:
@ComponentScan(basePackages = { "com.huangx.springboot.controller", "com.huangx.springboot.controller2" }, excludeFilters = { // 根据注解类型过滤,过滤拥有 MyAnnotation 注解的 Bean @ComponentScan.Filter(type = FilterType.ANNOTATION, classes = { MyAnnotation.class }), // 使用自定义的过滤器过滤Bean @ComponentScan.Filter(type = FilterType.CUSTOM, classes = { MyTypeFilter.class }), // 使用正则表达式过滤Bean, 下面将过滤 DateController 类 @ComponentScan.Filter(type = FilterType.REGEX, pattern = { ".+DateController" }), // 使用 AspectJ 表达式过滤 com.huangx.springboot.controller2 包及子包下面所有类的所有方法 @ComponentScan.Filter(type = FilterType.ASPECTJ, pattern = { "com.huangx.springboot.controller2..*" }) } )
指定哪些类型适合进行组件扫描。实例:
@ComponentScan(basePackages = { "com.huangx.springboot.controller", "com.huangx.springboot.controller2" }, includeFilters = { // 根据注解类型过滤,过滤拥有 MyAnnotation 注解的 Bean @ComponentScan.Filter(type = FilterType.ANNOTATION, classes = { MyAnnotation.class }), // 使用自定义的过滤器过滤Bean @ComponentScan.Filter(type = FilterType.REGEX, pattern = { "com.huangx.springboot.controller.model.*" }) }, useDefaultFilters = false )
注意:如果你想要使你上面定义的 @ComponentScan.Filter 有效,必须将 useDefaultFilters 设置为 false。
指定是否应该为延迟初始化注册扫描bean。实例:
@ComponentScan(basePackages = { "com.huangx.springboot.controller", "com.huangx.springboot.controller2"}, lazyInit = true )
BeanNameGenerator 类用于在 Spring 容器中命名检测到的组件。实例:
@ComponentScan(basePackages = { "com.huangx.springboot.controller", "com.huangx.springboot.controller2" }, nameGenerator = MyBeanNameGenerator.class )
其中,MyBeanNameGenerator 类代码如下:
package com.huangx.springboot.springboot_componentscan_demo1.custom; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.support.BeanDefinitionRegistry; import org.springframework.beans.factory.support.BeanNameGenerator; /** * 自定义Bean名称生成器 */ public class MyBeanNameGenerator implements BeanNameGenerator { @Override public String generateBeanName(BeanDefinition beanDefinition, BeanDefinitionRegistry beanDefinitionRegistry) { // 创建格式为 hxstrive_beanName 的 Bean 名称 String className = beanDefinition.getBeanClassName(); String simpleName = className.substring(className.lastIndexOf(".") + 1); return "hxstrive_" + String.valueOf(simpleName.charAt(0)).toLowerCase() + simpleName.substring(1); } }
上面的 MyBeanNameGenerator 类将在 generateBeanName() 方法中按照“hxstrive_Bean名称”(注意:Bean名称仅仅将类的名称第一个字符转换成小写)格式生产 Spring Bean 名称。例如:MyBean 生成的名字为 hxstrive_myBean。
控制有资格进行组件检测的类文件。实例:
@ComponentScan(basePackages = { "com.huangx.springboot.controller", "com.huangx.springboot.controller2"}, resourcePattern = "**/*Controller.class" )
上面实例仅仅扫描所有以 Controller.class 结尾的文件。
指示是否应该为检测到的组件生成代理,当以代理样式使用作用域时,这可能是必要的。ScopedProxyMode 枚举取值如下:
DEFAULT:默认值通常等于NO,除非在 component-scan 指令级别配置了其他默认值。
NO:不要创建作用域代理。当与非单作用域实例一起使用时,此代理模式通常不可用,如果将其用作依赖项,则应优先使用 INTERFACES 或 TARGET_CLASS 代理模式。
INTERFACES:创建一个JDK动态代理,以实现目标对象的类公开的所有接口。
TARGET_CLASS:创建一个基于类的代理(使用CGLIB)。
实例:指定使用 CGLIB 生成类的代理。
@ComponentScan(basePackages = { "com.huangx.springboot.controller", "com.huangx.springboot.controller2" }, scopedProxy = ScopedProxyMode.TARGET_CLASS )
ScopeMetadataResolver 用于解析所检测组件的范围。实例:
@ComponentScan(basePackages = { "com.huangx.springboot.controller", "com.huangx.springboot.controller2" }, scopeResolver = MyScopeMetadataResolver.class )
其中,MyScopeMetadataResolver 类代码如下:
package com.huangx.springboot.springboot_componentscan_demo1.custom; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.context.annotation.ScopeMetadata; import org.springframework.context.annotation.ScopeMetadataResolver; import org.springframework.context.annotation.ScopedProxyMode; /** * 自定义 ScopeMetadataResolver */ public class MyScopeMetadataResolver implements ScopeMetadataResolver { @Override public ScopeMetadata resolveScopeMetadata(BeanDefinition definition) { ScopeMetadata scopeMetadata = new ScopeMetadata(); // 设置每个 Bean 不是单例的,每次都会创建新的 Bean scopeMetadata.setScopeName(BeanDefinition.SCOPE_PROTOTYPE); // 使用 CGLIB 实现类代理 scopeMetadata.setScopedProxyMode(ScopedProxyMode.TARGET_CLASS); return scopeMetadata; } }
指示是否应该启用对带有@Component、@Repository、@Service 或 @Controller 注释的类的自动检测。实例:
@ComponentScan(basePackages = { "com.huangx.springboot.controller", "com.huangx.springboot.controller2" }, useDefaultFilters = false )
上面实例将 useDefaultFilters 设置为 false,这将导致 com.huangx.springboot.controller 和 com.huangx.springboot.controller2 包及子包下面所有显式或隐式声明了 @Component、@Repository、@Service 或 @Controller 注解的类不被扫描。