dependency:analyze 报“Unused declared dependencies”却不敢删,因其仅分析主/测试代码中显式 import 的类,无法识别反射、SPI、配置文件(如 application.yml)、@ConditionalOnClass、字节码增强等间接引用;例如 jackson-databind 仅在配置中使用也会被误判为 unused,删除后启动即报 NoClassDefFoundError。

dependency:analyze 为什么经常报“Unused declared dependencies”却不敢删?
它只检查 compile 和 runtime 作用域下被源码直接 import 的类,不追踪反射、SPI、配置文件加载、测试代码、字节码增强等间接引用。比如你用了 com.fasterxml.jackson.core:jackson-databind,但只在 application.yml 里配了 spring.jackson.date-format,dependency:analyze 就会把它标为 unused——删掉后启动直接报 NoClassDefFoundError。
真正安全的删除前提只有两个:该依赖既没被任何 .java 文件 import,也没被任何非编译期静态解析机制(如 Spring Boot 的 @ConditionalOnClass、MyBatis 的 TypeHandler 注册)隐式依赖。
- 运行前先加
-DignoreNonCompileScope=false(默认 true),否则连test作用域都跳过,结果更不准 - 加上
-DfailOnWarning=false避免构建中断,毕竟警告不等于错误 - 对多模块项目,必须在每个子模块目录下单独执行,父 POM 运行无效
如何区分“真冗余”和“假冗余”依赖?
关键看依赖是否出现在 mvn dependency:tree -Dincludes=groupId:artifactId 的输出路径中,且没有被任何上游模块传递引入。如果一个 unused 依赖同时满足:不在 dependency:tree 的任何路径上,且没被 resources/ 下的配置文件名、类名字符串匹配到(比如 logback-spring.xml 里写了 ch.qos.logback),那它大概率是真冗余。
- 用
grep -r "artifactId" src/main/resources/快速扫配置文件 - 用
mvn dependency:tree -Dverbose | grep -A5 -B5 "unused-artifact"看它是否被其他依赖暗中拉入 - 特别注意
provided作用域:Tomcat 或 JDK 提供的类(如javax.servlet:javax.servlet-api)即使未 import 也不该删
为什么 dependency:analyze-only 比 dependency:analyze 更可靠?
dependency:analyze 默认只分析主代码(src/main/java),而 dependency:analyze-only 可通过参数控制分析范围,比如加上 -DincludeTests=true 就能覆盖测试代码里的反射调用;再配合 -DignoreNonCompileScope=false,能暴露更多隐藏依赖关系。
- 推荐命令:
mvn dependency:analyze-only -DignoreNonCompileScope=false -DincludeTests=true -DfailOnWarning=false - 输出里的
Used undeclared dependencies表示有代码用了但没声明——这比 “unused” 更危险,得立刻补<dependency></dependency> - 若项目含 Kotlin/Scala,需额外加
-DignoredDependencies=org.jetbrains.kotlin:.*排除语言运行时干扰
删依赖后服务启动失败,最可能漏查哪三处?
不是 classpath 冲突,也不是版本问题,而是三个常被忽略的间接加载点:
-
META-INF/services/下的 SPI 文件(如java.sql.Driver)会触发类加载,哪怕没写 import - Spring Boot 的
spring.factories或spring-devtools.properties里声明的自动配置类 - Lombok 的
@Data、MapStruct 的@Mapper等注解处理器依赖,它们在编译期生效,dependency:analyze完全看不见
删之前至少跑一次 mvn compile test-compile,再用 find target/classes -name "*.class" | xargs javap -cp target/classes -s 2>/dev/null | grep "YourUnusedDependency" 确认字节码里真没残留引用。

















