SpringBoot @ComponentScan扫描包排除指定类配置不生效问题
SpringBoot @ComponentScan 排除类配置不生效问题
问题场景
开发SpringBoot应用时,配置组件扫描规则覆盖com.training包,期望排除SDIAuthorizerConfig.java类不被Spring容器加载,但排除配置始终未生效,应用部署到Tomcat启动时直接抛出依赖注入错误。
现有启动类配置
package com.training.execution.tom.action; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.netflix.eureka.EnableEurekaClient; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.ComponentScan.Filter; import com.training.foundation.core.application.SDIServiceApplication; import com.training.foundation.core.authorizer.config.SDIAuthorizerConfig; import org.springframework.context.annotation.FilterType; import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; @SpringBootApplication @ComponentScan(basePackages = "com.training",excludeFilters = @Filter(type= FilterType.ASSIGNABLE_TYPE, value=SDIAuthorizerConfig.class)) @EnableGlobalMethodSecurity(securedEnabled = true) @EnableEurekaClient @EnableAutoConfiguration public class TOMActionServiceApplication extends SDIServiceApplication{ public static void main(String[] args) { SpringApplication.run(TOMActionServiceApplication.class, args); } }
启动报错信息
Error starting Tomcat context. Exception: org.springframework.beans.factory.UnsatisfiedDependencyException. Message: Error creating bean with name 'SDIAuthorizerFilter': Unsatisfied dependency expressed through field 'authorizer'; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'SDILDAPAuthorizer': Unsatisfied dependency expressed through field 'populator'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'SDIAuthorizerConfig': Injection of autowired dependencies failed; nested exception is java.lang.IllegalArgumentException: Could not resolve placeholder 'sdi.ldap.url' in value "${sdi.ldap.url}"
报错根源是SDIAuthorizerConfig类中引用了配置占位符${sdi.ldap.url},当前环境无对应配置项导致依赖注入失败,但已配置的@ComponentScan排除规则未生效,类依然被容器加载。
失效原因
@ComponentScan注解的excludeFilters规则仅对当前扫描路径下标注了@Component/@Service/@Configuration等构造型注解、通过包扫描直接注册的Bean生效,对以下来源的Bean无效:
- 被其他配置类通过
@Import注解显式导入的类 - 通过
spring.factories注册的自动配置类 - 启动类继承的父类上挂载的配置类引入的Bean
另外当前配置重复声明了@ComponentScan和@EnableAutoConfiguration(@SpringBootApplication已经内置这两个注解的能力),容易出现配置优先级混乱,导致自定义排除规则被覆盖。
解决方案
- 移除启动类上重复的
@ComponentScan和@EnableAutoConfiguration注解,直接在@SpringBootApplication注解上统一配置扫描规则和排除项,自动配置级别的Bean需要通过exclude属性排除,而不是@ComponentScan的过滤器:
@SpringBootApplication( scanBasePackages = "com.training", exclude = SDIAuthorizerConfig.class ) @EnableGlobalMethodSecurity(securedEnabled = true) @EnableEurekaClient public class TOMActionServiceApplication extends SDIServiceApplication{ public static void main(String[] args) { SpringApplication.run(TOMActionServiceApplication.class, args); } }
- 如果上述配置依然不生效,说明
SDIAuthorizerConfig是依赖包内注册的自动配置类,可以在配置文件中追加自动配置排除规则:
spring: autoconfigure: exclude: - com.training.foundation.core.authorizer.config.SDIAuthorizerConfig
- 排查启动类父类
SDIServiceApplication的注解声明,如果父类上存在@Import(SDIAuthorizerConfig.class)或者额外的@ComponentScan规则,需要针对性重写配置排除该类。 - 启动时添加
--debug参数,控制台会输出完整的Bean加载报告,搜索SDIAuthorizerConfig即可看到该类的具体加载来源,再做针对性排除。
如果后续业务需要使用
SDIAuthorizerConfig提供的授权能力,不需要排除类的话,直接在配置文件中补全sdi.ldap.url等对应的必填配置项即可解决启动报错。
内容的提问来源于stack exchange,提问作者Vikram Srinivasan
相关产品推荐
相关产品推荐

