上一个章节介绍了 @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 注解的类不被扫描。