添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
专注于 JetBrains IDEA 全家桶,永久激活,教程
持续更新 PyCharm,IDEA,WebStorm,PhpStorm,DataGrip,RubyMine,CLion,AppCode 永久激活教程
  • JetBrains 全家桶破解
  • 精选500套教程
  • @ComponentScan属性basePackages 与 valuebasePackageClassesincludeFiltersexcludeFilters添加自定义过滤规则@Component@ComponentScanscontext:component-scanSpringBootApplication 注解中4个方法小结参考文献

    @ComponentScan

    在讲述 @Configuration 启动容器+ @Component 注册 Bean 小节中简单介绍了 @ComponentScan 注解的使用。

    @ComponentScan 的功能其实就是自动扫描并加载符合条件的组件或 bean 定义,最终将这些 bean 定义加载到容器中。 我们可以通过 backPackages 等属性指定@ComponentScan 自动扫描的范围,如果不指定,则默认 Spring 框架实现从声明@ComponentScan 所在类的 package 进行扫描,默认情况下是不指定的,所以 SpringBoot 的启动类最好在 root package 下。

    首先看下 @ComponentScan 的源码:

    @Retention(RetentionPolicy.RUNTIME)
    @Target({ElementType.TYPE})
    @Documented
    @Repeatable(ComponentScans.class)
    public @interface ComponentScan {
        @AliasFor("basePackages")
        String[] value() default {};
        @AliasFor("value")
        String[] basePackages() default {};
        Class<?>[] basePackageClasses() default {};
        Class<? extends BeanNameGenerator> nameGenerator() default BeanNameGenerator.class;
        Class<? extends ScopeMetadataResolver> scopeResolver() default AnnotationScopeMetadataResolver.class;
        ScopedProxyMode scopedProxy() default ScopedProxyMode.DEFAULT;
        String resourcePattern() default "**/*.class";
        boolean useDefaultFilters() default true;
        ComponentScan.Filter[] includeFilters() default {};
        ComponentScan.Filter[] excludeFilters() default {};
        boolean lazyInit() default false;
        @Retention(RetentionPolicy.RUNTIME)
        @Target({})
        public @interface Filter {
            FilterType type() default FilterType.ANNOTATION;
            @AliasFor("classes")
            Class<?>[] value() default {};
            @AliasFor("value")
            Class<?>[] classes() default {};
            String[] pattern() default {};
    

    重点有以下几个属性:

  • basePackages 与 value:用于指定包的路径进行扫描;
  • basePackageClasses:用于指定某个类的包的路径进行扫描;
  • nameGenerator:bean 的名称的生成器;
  • useDefaultFilters:是否开启对@Component,@Repository,@Service,@Controller 的类进行检测,默认为 true;
  • includeFilters:包含的过滤条件 FilterType.ANNOTATION:按照注解过滤; FilterType.ASSIGNABLE_TYPE:按照给定的类型;FilterType.ASPECTJ:使用 ASPECTJ 表达式;FilterType.REGEX:正则;FilterType.CUSTOM:自定义规则 。
  • excludeFilters:排除的过滤条件,用法和 includeFilters 一样。
  • basePackages 与 value
    @ComponentScan(basePackages = “”)     //单个
    @ComponentScan(basePackages = {“com.example.dao”,“aaa”,“…”})   //多个
    //value 同理
    

    注意:可以省略 “ basePackages = ”。

    @Configuration
    @ComponentScan("com.example.dao")
    public class MyConfig {}
    @Configuration
    @ComponentScan("com.example.dao","com.example.service")
    public class MyConfig {}
    @Configuration
    @ComponentScan("com.example.*")   //通配符匹配所有的包
    public class MyConfig {}
    
    basePackageClasses
    @ComponentScan(basePackageClasses = “”)   //单个
    @ComponentScan(basePackageClasses = {“HelloController.class”,“bbb”,“…”})  //多个
    

    注意:不可以省略“basePackageClasses =”

    @Configuration
    @ComponentScan(basePackageClasses = HelloController.class)
    public class MyConfig {
    
    includeFilters

    接下来我们用以下代码进行测试。

    Repository 的注解类:

    package com.example.dao;
    @Repository
    public class BusinessDAO {
        public void update(){
            System.out.println("调用了 dao 层的 update 方法....");
    

    Service 的注解类:

    package com.example.service;
    @Service
    public class BusinessService {
        @Autowired
        private BusinessDAO businessDAO;
        public void service(){
            System.out.println("调用了 service 层的 service() 方法 .....");
            businessDAO.update();
    

    Controller 的注解类:

    package com.example.controller;
    @Controller
    public class BusinessController {
        @Autowired
        private BusinessService service;
        public void request() {
            System.out.println(" 调用了 Controller 的 request() 方法...");
            service.service();
    

    Configuration 配置类:

    package com.example.configuration;
    @Configuration
    //@ComponentScan(basePackages = {"com.example.dao","com.example.service","com.example.controller"})
    @ComponentScan(value = {"com.example.dao","com.example.service","com.example.controller"},
            includeFilters = {@ComponentScan.Filter(type = FilterType.ANNOTATION,classes = Repository.class)},
            useDefaultFilters = false)
    public class ScanConfig {
    

    测试类代码:

    public class ScanConfigTest {
        public static void main(String[] args) {
            AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ScanConfig.class);
            String[] definitionNames = context.getBeanDefinitionNames();
            for(String name:definitionNames){
                System.out.println(name);
    

    执行结果为:

    19:22:48.157 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'scanConfig'
    19:22:48.162 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'businessDAO'
    org.springframework.context.annotation.internalConfigurationAnnotationProcessor
    org.springframework.context.annotation.internalAutowiredAnnotationProcessor
    org.springframework.context.annotation.internalCommonAnnotationProcessor
    org.springframework.context.event.internalEventListenerProcessor
    org.springframework.context.event.internalEventListenerFactory
    scanConfig
    businessDAO
    

    根据结果分析: 除了 spring 本身注册的一些 bean 之外,可以看到最后一行,已经将 ScanConfig 这个类和 BusinessDAO 注册进容器中了。

    includeFilters 的参数是一个 Filter[] 数组,然后指定 FilterType 的类型为 ANNOTATION,也就是通过注解来过滤,最后的 value 则是 Repository 注解类。配置之后,在 spring 扫描的时候,就会筛选 com.example 下的三个包中,所有被 @Repository 注解标注的类。

    注意:需要设置 useDefaultFilters 为 false,否则@ComponentScan 注解会将 被 @Component、@Repository、@Service 和 @Controller 标注的类都注册进容器中。同时因为我们在 Controller 和 Service 注解的类中关联了其他的类(@Autowired),所以最好在 includeFilters 的 Filter 属性中不要设置为 Controller.class 或 Service.class。

    excludeFilters

    修改配置类:

    @Configuration
    //@ComponentScan(basePackages = {"com.example.dao","com.example.service","com.example.controller"})
    @ComponentScan(value = {"com.example.dao","com.example.service","com.example.controller"},
            excludeFilters = {@ComponentScan.Filter(type = FilterType.ANNOTATION,classes = Controller.class)})
    public class ScanConfig {
    

    同 excludeFilters 属性类似, 配置之后,在 spring 扫描的时候,就会跳过 com.example 下的三个包中,所有被 @Controller 注解标注的类。

    执行结果为:

    19:44:39.191 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'scanConfig'
    19:44:39.195 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'businessDAO'
    19:44:39.195 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'businessService'
    org.springframework.context.annotation.internalConfigurationAnnotationProcessor
    org.springframework.context.annotation.internalAutowiredAnnotationProcessor
    org.springframework.context.annotation.internalCommonAnnotationProcessor
    org.springframework.context.event.internalEventListenerProcessor
    org.springframework.context.event.internalEventListenerFactory
    scanConfig
    businessDAO
    businessService
    
    添加自定义过滤规则

    在前面使用过 @Filter 注解,里面的 type 属性是一个 FilterType 的枚举类型:

    public enum FilterType {
        ANNOTATION,
        ASSIGNABLE_TYPE,
        ASPECTJ,
        REGEX,
        CUSTOM
    

    使用 CUSTOM 类型,就可以实现自定义过滤规则。

    package com.example.filter;
    public class CustomTypeFilter implements TypeFilter {
        @Override
        public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException {
            // 获取当前扫描到的类的注解元数据
            AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata();
            // 获取当前扫描到的类的元数据
            ClassMetadata classMetadata = metadataReader.getClassMetadata();
            // 获取当前扫描到的类的资源信息
            Resource resource = metadataReader.getResource();
            if (classMetadata.getClassName().contains("Business")){
                return true;
            return false;
    

    增加 Service 注解修饰的类:

    package com.example.service;
    @Service
    public class UserService {
    

    修改配置类:

    @Configuration
    @ComponentScan(value = {"com.example.dao","com.example.service","com.example.controller"},
            excludeFilters = {@ComponentScan.Filter(type = FilterType.CUSTOM,classes = CustomTypeFilter.class)})
    public class ScanConfig {
    

    执行测试类代码,结果为:

    19:56:25.419 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'scanConfig'
    19:56:25.424 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'userService'
    org.springframework.context.annotation.internalConfigurationAnnotationProcessor
    org.springframework.context.annotation.internalAutowiredAnnotationProcessor
    org.springframework.context.annotation.internalCommonAnnotationProcessor
    org.springframework.context.event.internalEventListenerProcessor
    org.springframework.context.event.internalEventListenerFactory
    scanConfig
    userService
    

    这里简单对扫描到的类名进行判断,如果类名包含”Business“的就符合条件,就会被剔除,不会注入到容器中。

    @Component

    1、不指定 bean 的名称,默认为类名首字母小写 university

    @Component
    public class BeanWithComponent {
        public void sayHello(){
            System.out.println("BeanWithComponent sayHello...");
        public void start(){
            System.out.println("BeanWithComponent 初始化。。。");
        public void cleanUp(){
            System.out.println("BeanWithComponent 销毁。。。");
    

    获取 bean 方式:

    @Autowired
    BeanWithComponent beanWithComponent;
    
    ApplicationContext context = new AnnotationConfigApplicationContext(ComfigureWithScan.class);
    BeanWithComponent bean = (BeanWithComponent) context.getBean("beanWithComponent");
    

    2、指定 bean 的名称

    @Component("bean2")
    public class BeanWithComponent {
    

    获取 bean 方式:

    @Autowired
    BeanWithComponent bean2;
    
    ApplicationContext context = new AnnotationConfigApplicationContext(ComfigureWithScan.class);
    BeanWithComponent bean = (BeanWithComponent) context.getBean("bean2");
    

    @ComponentScan 注解有以下特性:

  • 自定义扫描路径下边带有@Controller@Service@Repository@Component 注解加入 spring 容器
  • 通过 includeFilters 加入扫描路径下没有以上注解的类加入 spring 容器
  • 通过 excludeFilters 过滤出不用加入 spring 容器的类
  • 自定义增加了@Component 注解的注解方式
  • 接下来讲述一下关于@ComponentScan 注解的两个扩展。

    @ComponentScans

    源码如下:

    @Retention(RetentionPolicy.RUNTIME)
    @Target({ElementType.TYPE})
    @Documented
    public @interface ComponentScans {
        ComponentScan[] value();
    
    @Configuration
    @ComponentScans(value = @ComponentScan("com.example.dao"))
    public class ScanConfig {
    

    执行结果为:

    20:07:45.908 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'scanConfig'
    20:07:45.914 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'businessDAO'
    org.springframework.context.annotation.internalConfigurationAnnotationProcessor
    org.springframework.context.annotation.internalAutowiredAnnotationProcessor
    org.springframework.context.annotation.internalCommonAnnotationProcessor
    org.springframework.context.event.internalEventListenerProcessor
    org.springframework.context.event.internalEventListenerFactory
    scanConfig
    businessDAO
    

    context:component-scan

    上述代码我们是通过@Configuration + @ComponentScan 注解来实现 spring 加载,当然也可以在配置文件中加上扫描的配置。

    spring-context.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns:context="http://www.springframework.org/schema/context"
           xsi:schemaLocation="http://www.springframework.org/schema/beans
               http://www.springframework.org/schema/beans/spring-beans.xsd
               http://www.springframework.org/schema/context
               http://www.springframework.org/schema/context/spring-context-3.0.xsd">
        <!--<context:component-scan base-package="com.example.dao" annotation-config="false">
            <context:include-filter type="annotation" expression="org.springframework.stereotype.Repository"/>
        </context:component-scan>-->
        <context:component-scan base-package="com.example.dao" />
        <context:component-scan base-package="com.example.controller" />
        <context:component-scan base-package="com.example.service" />
    </beans>
    

    修改测试类代码:

    public class ScanConfigTest {
        public static void main(String[] args) {
            ApplicationContext  context = new ClassPathXmlApplicationContext("spring-context.xml");
            String[] definitionNames = context.getBeanDefinitionNames();
            for(String name:definitionNames){
                System.out.println(name);
    

    运行得到以下结果:

    14:59:12.773 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'businessDAO'
    14:59:12.778 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'businessController'
    14:59:12.789 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'businessService'
    14:59:12.789 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'userService'
    businessDAO
    org.springframework.context.annotation.internalConfigurationAnnotationProcessor
    org.springframework.context.annotation.internalAutowiredAnnotationProcessor
    org.springframework.context.annotation.internalCommonAnnotationProcessor
    org.springframework.context.event.internalEventListenerProcessor
    org.springframework.context.event.internalEventListenerFactory
    businessController
    businessService
    userService
    

    关于 的使用,关于属性的详细讲解可以参考:详解

    注意: 中有一个 annotation-config 属性,该属性主要是隐式地向 Spring 容器注册 internalConfigurationAnnotationProcessorinternalAutowiredAnnotationProcessorinternalCommonAnnotationProcessorinternalEventListenerProcessor 以及 internalEventListenerFactory 这五个 bean 类。

    当 annotation-config 属性值设为 false 时,即不会注册这五个类。但是@ComponentScan 注解没有该属性。 这是因为在几乎所有情况下,使用@ComponentScan 时,都假定使用默认的注释配置处理(例如,处理@Autowired 和 friends )。 此外,在使用AnnotationConfigApplicationContext 时,注释配置处理器始终会被注册,这意味着在@ComponentScan 级别禁用它们的任何尝试都将被忽略。

    SpringBootApplication 注解中4个方法

    @SpringBootApplication不仅包括上面的三个重要注解,还包含有4个方法:

  • Class[] exclude() default {}; 根据 Class 来排除特定的类加入 Spring 容器,传入参数是 class 类型;
  • String[] excludeName() default {}; 根据 Class Name 排除特定的类加入 Spring 容器,传入参数是 class 的全类名字字符串数组;
  • String[] scanBasePackages() default {}; 指定扫描包,参数是包名的字符串数组;
  • Class[] scanBasePackageClasses() default {}; 指定扫描包,参数是 Class 类型数组。
  • 这里总结下@SpringBootApplication 中的三个重要注解的特征:

  • @Configuration
  • 定义 Spring Ioc 容器的配置类。

  • @EnableAutoConfiguration
  • 从 classpath 中搜寻所有 META/spring.factories 配置文件,并将其中org.springframework.boot.autoconfigure.EnableAutoConfiguration 对应的配置项,也就是一个自动配置类列表加载到 Ioc 容器中。 简单说,就是@EnawebleAutoConfiguration 让 Spring Boot 根据类路径下的 jar 包依赖为当前项目进行自动配置,例如,添加了 spring-boot-starter-web 依赖,会自动添加 Tomcat 和 Spring MVC 的依赖。而对于所有标注@Configuration 的配置类,统一使用ConfigurationClassParser解析的。

  • @ComponentScan
  • 自动扫描并加载符合条件的组件或者 bean 定义。

    spring4.0之二:@Configuration的使用

    springboot系列文章之SpringBootApplication注解

    文章永久链接:https://tech.souyunku.com/18869

    未经允许不得转载:搜云库技术团队 » Spring Boot注解学习之@SpringBootApplication(二)

    JetBrains 全家桶,激活、破解、教程

    提供 JetBrains 全家桶激活码、注册码、破解补丁下载及详细激活教程,支持 IntelliJ IDEA、PyCharm、WebStorm 等工具的永久激活。无论是破解教程,还是最新激活码,均可免费获得,帮助开发者解决常见激活问题,确保轻松破解并快速使用 JetBrains 软件。获取免费的破解补丁和激活码,快速解决激活难题,全面覆盖 2024/2025 版本!

    联系我们联系我们
    京ICP备17065017号 | 京公网安备11011102002472号

    © 2010-2025   搜云库技术团队   网站地图