Spring Boot 教程

@ComponentScan 注解(2)

上一个章节介绍了 @ComponentScan 注解的基础用法,该章节将详细介绍 @ComponentScan 注解每个属性的用法。@ComponentScan注解支持如下属性:

Class<?>[] basePackageClasses

basePackages() 的类型安全替代方案,用于指定要扫描的组件以扫描带注释的组件。实例:

@ComponentScan(basePackageClasses = {
        IndexController.class,
        DateController.class
})

上面实例将扫描 com.huangx.springboot.controller 和 com.huangx.springboot.controller2 包以及子包。

String[] basePackages

用于扫描带注解的组件的基本包。实例:

@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 包以及子包。

String[] value

basePackages() 别名。实例见 basePackages

ComponentScan.Filter[] excludeFilters

指定哪些类型不符合组件扫描的条件。实例:

@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.Filter[] includeFilters

指定哪些类型适合进行组件扫描。实例:

@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。

boolean lazyInit

指定是否应该为延迟初始化注册扫描bean。实例:

@ComponentScan(basePackages = {
        "com.huangx.springboot.controller",
        "com.huangx.springboot.controller2"},
        lazyInit = true
)

Class<? extends BeanNameGenerator> nameGenerator

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。

String resourcePattern

控制有资格进行组件检测的类文件。实例:

@ComponentScan(basePackages = {
        "com.huangx.springboot.controller",
        "com.huangx.springboot.controller2"},
        resourcePattern = "**/*Controller.class"
)

上面实例仅仅扫描所有以 Controller.class 结尾的文件。

ScopedProxyMode scopedProxy 

指示是否应该为检测到的组件生成代理,当以代理样式使用作用域时,这可能是必要的。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
)

Class<? extends ScopeMetadataResolver> scopeResolver

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;
    }

}

boolean useDefaultFilters

指示是否应该启用对带有@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 注解的类不被扫描。

说说我的看法
全部评论(
没有评论
关于
本网站属于个人的非赢利性网站,转载的文章遵循原作者的版权声明,如果原文没有版权声明,请来信告知:hxstrive@outlook.com
公众号