maven scope=provided || optional=true会打包到jar文件中吗?

发布于:2025-09-05 ⋅ 阅读:(21) ⋅ 点赞:(0)

问题描述

Maven中的依赖<scope>provided</scope><optional>true</optional>是否会打包到最终的jar包中?

 <dependency>
     <groupId>org.apache.commons</groupId>
     <artifactId>commons-lang3</artifactId>
     <scope>provided</scope>
 </dependency>
 <dependency>
     <groupId>commons-beanutils</groupId>
     <artifactId>commons-beanutils</artifactId>
     <version>1.9.4</version>
     <optional>true</optional>
 </dependency>

先说结论:
1、如果是pringboot的打包插件,即使你设置了以上两个属性这两个依赖依然会被打包到可执行jar包中。这是SpringBoot的机制,具体看下文分析。
2、如果是普通原生的maven打包上面两者是不会打包到jar文件中的。

现象分析

探讨分析Spring Boot打包时<scope>provided</scope><optional>true</optional>的行为,两者是否需要被打打包到可执行jar包的BOOT-INFO/lib目录下?

现在让我分析打包后的jar文件,看看实际包含的依赖情况:

cd /Users/shouzhi/nvxclouds/project/springboot-x-example && jar -tf target/springboot-x-example-1.0.0.jar | grep -E "(commons-lang3|commons-beanutils)" | head -10

输出输出>>>>>>
<ep -E "(commons-lang3|commons-beanutils)" | head -10
BOOT-INF/lib/commons-lang3-3.12.0.jar
BOOT-INF/lib/commons-beanutils-1.9.4.jar

现在分析一下Maven的依赖树,看看这些依赖是如何被引入的:

mvn dependency:tree | grep -A 5 -B 5 -E "(commons-lang3|commons-beanutils)"

输出>>>>>>
Downloading from nexus: http://192.168.50.16:8081/repository/maven-public/com/nvxclouds/baize/tally/tally-co
mmon-s3/3.2.0-springboot2-jdk8-SNAPSHOT/maven-metadata.xml

Downloaded from nexus: http://192.168.50.16:8081/repository/maven-public/com/nvxclouds/baize/tally/tally-com
mon-s3/3.2.0-springboot2-jdk8-SNAPSHOT/maven-metadata.xml (841 B at 49 kB/s)

[INFO] 
[INFO] --- dependency:3.3.0:tree (default-cli) @ springboot-x-example ---
[INFO] com.shouzhi.test:springboot-x-example:jar:1.0.0
[INFO] +- org.apache.commons:commons-lang3:jar:3.12.0:provided
[INFO] +- commons-beanutils:commons-beanutils:jar:1.9.4:compile
[INFO] |  +- commons-logging:commons-logging:jar:1.2:compile
[INFO] |  \- commons-collections:commons-collections:jar:3.2.2:compile
[INFO] +- org.springframework.boot:spring-boot-starter-web:jar:2.7.18:compile
[INFO] |  +- org.springframework.boot:spring-boot-starter:jar:2.7.18:compile
[INFO] |  |  +- org.springframework.boot:spring-boot:jar:2.7.18:compile

查看完整的依赖树来全面分析:

mvn dependency:tree

输出>>>>>>
......

Downloaded from nexus: http://192.168.50.16:8081/repository/maven-public/com/nvxclouds/baize/tally/tally-com
mon-s3/3.2.0-springboot2-jdk8-SNAPSHOT/maven-metadata.xml (841 B at 44 kB/s)

[INFO] 
[INFO] --- dependency:3.3.0:tree (default-cli) @ springboot-x-example ---
[INFO] com.shouzhi.test:springboot-x-example:jar:1.0.0
[INFO] +- org.apache.commons:commons-lang3:jar:3.12.0:provided
[INFO] +- commons-beanutils:commons-beanutils:jar:1.9.4:compile
[INFO] |  +- commons-logging:commons-logging:jar:1.2:compile
[INFO] |  \- commons-collections:commons-collections:jar:3.2.2:compile
[INFO] +- org.springframework.boot:spring-boot-starter-web:jar:2.7.18:compile
[INFO] |  +- org.springframework.boot:spring-boot-starter:jar:2.7.18:compile
[INFO] |  |  +- org.springframework.boot:spring-boot:jar:2.7.18:compile
[INFO] |  |  +- org.springframework.boot:spring-boot-autoconfigure:jar:2.7.18:compile
[INFO] |  |  +- org.springframework.boot:spring-boot-starter-logging:jar:2.7.18:compile
[INFO] |  |  |  +- ch.qos.logback:logback-classic:jar:1.2.12:compile
[INFO] |  |  |  |  \- ch.qos.logback:logback-core:jar:1.2.12:compile
[INFO] |  |  |  +- org.apache.logging.log4j:log4j-to-slf4j:jar:2.17.2:compile
[INFO] |  |  |  |  \- org.apache.logging.log4j:log4j-api:jar:2.17.2:compile
[INFO] |  |  |  \- org.slf4j:jul-to-slf4j:jar:1.7.36:compile
[INFO] |  |  +- jakarta.annotation:jakarta.annotation-api:jar:1.3.5:compile
[INFO] |  |  \- org.yaml:snakeyaml:jar:1.30:compile
[INFO] |  +- org.springframework.boot:spring-boot-starter-json:jar:2.7.18:compile
[INFO] |  |  +- com.fasterxml.jackson.core:jackson-databind:jar:2.13.5:compile
[INFO] |  |  |  +- com.fasterxml.jackson.core:jackson-annotations:jar:2.13.5:compile
[INFO] |  |  |  \- com.fasterxml.jackson.core:jackson-core:jar:2.13.5:compile
[INFO] |  |  +- com.fasterxml.jackson.datatype:jackson-datatype-jdk8:jar:2.13.5:compile
[INFO] |  |  +- com.fasterxml.jackson.datatype:jackson-datatype-jsr310:jar:2.13.5:compile
[INFO] |  |  \- com.fasterxml.jackson.module:jackson-module-parameter-names:jar:2.13.5:compile
[INFO] |  +- org.springframework.boot:spring-boot-starter-tomcat:jar:2.7.18:compile
[INFO] |  |  +- org.apache.tomcat.embed:tomcat-embed-core:jar:9.0.83:compile
[INFO] |  |  +- org.apache.tomcat.embed:tomcat-embed-el:jar:9.0.83:compile
[INFO] |  |  \- org.apache.tomcat.embed:tomcat-embed-websocket:jar:9.0.83:compile
[INFO] |  +- org.springframework:spring-web:jar:5.3.31:compile
[INFO] |  |  \- org.springframework:spring-beans:jar:5.3.31:compile
[INFO] |  \- org.springframework:spring-webmvc:jar:5.3.31:compile
[INFO] |     +- org.springframework:spring-aop:jar:5.3.31:compile
[INFO] |     +- org.springframework:spring-context:jar:5.3.31:compile
[INFO] |     \- org.springframework:spring-expression:jar:5.3.31:compile
[INFO] +- org.springframework.boot:spring-boot-starter-test:jar:2.7.18:test
[INFO] |  +- org.springframework.boot:spring-boot-test:jar:2.7.18:test
[INFO] |  +- org.springframework.boot:spring-boot-test-autoconfigure:jar:2.7.18:test
[INFO] |  +- com.jayway.jsonpath:json-path:jar:2.7.0:test
[INFO] |  |  +- net.minidev:json-smart:jar:2.4.11:test
[INFO] |  |  |  \- net.minidev:accessors-smart:jar:2.4.11:test
[INFO] |  |  |     \- org.ow2.asm:asm:jar:9.3:test
[INFO] |  |  \- org.slf4j:slf4j-api:jar:1.7.36:compile
[INFO] |  +- jakarta.xml.bind:jakarta.xml.bind-api:jar:2.3.3:test
[INFO] |  |  \- jakarta.activation:jakarta.activation-api:jar:1.2.2:test
[INFO] |  +- org.assertj:assertj-core:jar:3.22.0:test
[INFO] |  +- org.hamcrest:hamcrest:jar:2.2:test
[INFO] |  +- org.junit.jupiter:junit-jupiter:jar:5.8.2:test
[INFO] |  |  +- org.junit.jupiter:junit-jupiter-api:jar:5.8.2:test
[INFO] |  |  |  +- org.opentest4j:opentest4j:jar:1.2.0:test
[INFO] |  |  |  +- org.junit.platform:junit-platform-commons:jar:1.8.2:test
[INFO] |  |  |  \- org.apiguardian:apiguardian-api:jar:1.1.2:test
[INFO] |  |  +- org.junit.jupiter:junit-jupiter-params:jar:5.8.2:test
[INFO] |  |  \- org.junit.jupiter:junit-jupiter-engine:jar:5.8.2:test
[INFO] |  |     \- org.junit.platform:junit-platform-engine:jar:1.8.2:test
[INFO] |  +- org.mockito:mockito-core:jar:4.5.1:test
[INFO] |  |  +- net.bytebuddy:byte-buddy:jar:1.12.23:test
[INFO] |  |  +- net.bytebuddy:byte-buddy-agent:jar:1.12.23:test
[INFO] |  |  \- org.objenesis:objenesis:jar:3.2:test
[INFO] |  +- org.mockito:mockito-junit-jupiter:jar:4.5.1:test
[INFO] |  +- org.skyscreamer:jsonassert:jar:1.5.1:test
[INFO] |  |  \- com.vaadin.external.google:android-json:jar:0.0.20131108.vaadin1:test
[INFO] |  +- org.springframework:spring-core:jar:5.3.31:compile
[INFO] |  |  \- org.springframework:spring-jcl:jar:5.3.31:compile
[INFO] |  +- org.springframework:spring-test:jar:5.3.31:test
[INFO] |  \- org.xmlunit:xmlunit-core:jar:2.9.1:test
[INFO] +- com.alibaba.fastjson2:fastjson2:jar:2.0.55:compile
[INFO] +- org.projectlombok:lombok:jar:1.18.30:compile
[INFO] +- com.nvxclouds.baize.tally:tally-common-tidb:jar:3.2.0-springboot2-jdk8-SNAPSHOT:compile
[INFO] |  +- javax.annotation:javax.annotation-api:jar:1.3.2:compile
[INFO] |  +- com.mysql:mysql-connector-j:jar:8.0.33:compile
[INFO] |  \- com.zaxxer:HikariCP:jar:4.0.3:compile
[INFO] \- com.nvxclouds.baize.tally:tally-common-s3:jar:3.2.0-springboot2-jdk8-SNAPSHOT:compile
[INFO]    \- com.amazonaws:aws-java-sdk-s3:jar:1.11.343:compile
[INFO]       +- com.amazonaws:aws-java-sdk-kms:jar:1.11.343:compile
[INFO]       +- com.amazonaws:aws-java-sdk-core:jar:1.11.343:compile
[INFO]       |  +- org.apache.httpcomponents:httpclient:jar:4.5.14:compile
[INFO]       |  |  +- org.apache.httpcomponents:httpcore:jar:4.4.16:compile
[INFO]       |  |  \- commons-codec:commons-codec:jar:1.15:compile
[INFO]       |  +- com.fasterxml.jackson.dataformat:jackson-dataformat-cbor:jar:2.13.5:compile
[INFO]       |  \- joda-time:joda-time:jar:2.8.1:compile
[INFO]       \- com.amazonaws:jmespath-java:jar:1.11.343:compile
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  0.997 s
[INFO] Finished at: 2025-09-03T08:35:30+08:00
[INFO] ------------------------------------------------------------------------

现在分析一下为什么会出现这种情况。首先让我检查一下是否有其他传递依赖引入了这些包:

mvn dependency:tree -Dincludes=org.apache.commons:commons-lang3

输出>>>>>>
[INFO] Scanning for projects...
[INFO] 
[INFO] ---------------< com.shouzhi.test:springboot-x-example >----------------
[INFO] Building tidb-test 1.0.0
[INFO]   from pom.xml
[INFO] --------------------------------[ jar ]---------------------------------
。。。。。。。

Downloaded from nexus: http://192.168.50.16:8081/repository/maven-public/com/nvxclouds/baize/tally/tally-com
mon-s3/3.2.0-springboot2-jdk8-SNAPSHOT/maven-metadata.xml (841 B at 44 kB/s)

[INFO] 
[INFO] --- dependency:3.3.0:tree (default-cli) @ springboot-x-example ---
[INFO] com.shouzhi.test:springboot-x-example:jar:1.0.0
[INFO] \- org.apache.commons:commons-lang3:jar:3.12.0:provided
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  0.902 s
[INFO] Finished at: 2025-09-03T08:35:41+08:00
[INFO] ------------------------------------------------------------------------
mvn dependency:tree -Dincludes=commons-beanutils:commons-beanutils

输出>>>>>>
[INFO] Scanning for projects...
[INFO] 
[INFO] ---------------< com.shouzhi.test:springboot-x-example >----------------
[INFO] Building tidb-test 1.0.0
[INFO]   from pom.xml
[INFO] --------------------------------[ jar ]---------------------------------
。。。。。。

Downloaded from nexus: http://192.168.50.16:8081/repository/maven-public/com/nvxclouds/baize/tally/tally-com
mon-s3/3.2.0-springboot2-jdk8-SNAPSHOT/maven-metadata.xml (841 B at 44 kB/s)

[INFO] 
[INFO] --- dependency:3.3.0:tree (default-cli) @ springboot-x-example ---
[INFO] com.shouzhi.test:springboot-x-example:jar:1.0.0
[INFO] \- commons-beanutils:commons-beanutils:jar:1.9.4:compile
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  0.921 s
[INFO] Finished at: 2025-09-03T08:35:45+08:00
[INFO] ------------------------------------------------------------------------

现在查看具体的Spring Boot Maven Plugin配置,看看是否有特殊设置:

mvn help:effective-pom | grep -A 20 -B 5 "spring-boot-maven-plugin"

输出>>>>>>
shouzhi@192 springboot-x-example % mvn help:effective-pom | grep -A 20 -B 5 "spring-boot-maven-plugin"
            </execution>
          </executions>
          <dependencies>
            <dependency>
              <groupId>org.springframework.boot</groupId>
              <artifactId>spring-boot-maven-plugin</artifactId>
              <version>2.7.18</version>
            </dependency>
          </dependencies>
          <configuration>
            <!--这个属性导致以上2个包仍然被导报到/lib中-->
            <keepDependenciesWithProvidedScope>true</keepDependenciesWithProvidedScope>
            <createDependencyReducedPom>true</createDependencyReducedPom>
            <filters>
              <filter>
                <artifact>*:*</artifact>
                <excludes>
                  <exclude>META-INF/*.SF</exclude>
                  <exclude>META-INF/*.DSA</exclude>
                  <exclude>META-INF/*.RSA</exclude>
                </excludes>
              </filter>
            </filters>
          </configuration>
        </plugin>
        <plugin>
          <artifactId>maven-source-plugin</artifactId>
--
            </archive>
          </configuration>
        </plugin>
        <plugin>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-maven-plugin</artifactId>
          <version>2.7.18</version>
          <executions>
            <execution>
              <id>repackage</id>
              <goals>
                <goal>repackage</goal>
              </goals>
              <configuration>
                <mainClass>${start-class}</mainClass>
              </configuration>
            </execution>
          </executions>
          <configuration>
            <mainClass>${start-class}</mainClass>
          </configuration>
        </plugin>
        <plugin>
          <groupId>org.codehaus.mojo</groupId>
          <artifactId>versions-maven-plugin</artifactId>
          <version>2.10.0</version>
--
      </plugins>
    </pluginManagement>
    <plugins>
      <plugin>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-maven-plugin</artifactId>
        <version>2.7.18</version>
        <executions>
          <execution>
            <id>repackage</id>
            <goals>
              <goal>repackage</goal>
            </goals>
            <configuration>
              <mainClass>${start-class}</mainClass>
            </configuration>
          </execution>
        </executions>
        <configuration>
          <mainClass>${start-class}</mainClass>
        </configuration>
      </plugin>
      <plugin>
        <artifactId>maven-clean-plugin</artifactId>
        <version>3.2.0</version>
        <executions>
shouzhi@192 springboot-x-example %

现在发现了关键问题!从有效POM中可以看到一个关键配置:<keepDependenciesWithProvidedScope>true</keepDependenciesWithProvidedScope>

问题分析

以上现象是正确的,这是 Spring Boot Maven Plugin 的默认行为,而不是bug。

根本原因

  1. Spring Boot 的"Fat JAR"策略

    • Spring Boot 创建的是自包含的可执行JAR(Fat JAR/Uber JAR)
    • 为了确保应用可以独立运行,它会默认包含所有依赖,包括 providedoptional 的依赖
  2. Spring Boot Maven Plugin 的默认配置

    • 从有效POM可以看到:<keepDependenciesWithProvidedScope>true</keepDependenciesWithProvidedScope>
    • 这个配置导致 provided 依赖也被打包进去
  3. 传统Maven vs Spring Boot的区别

    <!-- 传统Maven:provided依赖不会被打包 -->
    <scope>provided</scope>
    
    <!-- Spring Boot:默认仍会打包,确保独立运行 -->
    
    

验证结果解释

  • commons-lang3 (provided) → 被打包:因为 keepDependenciesWithProvidedScope=true
  • commons-beanutils (optional) → 被打包:optional主要影响传递依赖,当前项目中仍会被打包

如何控制打包行为

如果您确实不想让这些依赖被打包,可以在 spring-boot-maven-plugin 中显式排除:

<plugin>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-maven-plugin</artifactId>
    <configuration>
        <excludes>
            <exclude>
                <groupId>org.apache.commons</groupId>
                <artifactId>commons-lang3</artifactId>
            </exclude>
            <exclude>
                <groupId>commons-beanutils</groupId>
                <artifactId>commons-beanutils</artifactId>
            </exclude>
        </excludes>
    </configuration>
</plugin>

总结

验证结果是完全正确的!Spring Boot 的这种设计是有意为之,目的是创建一个完全自包含的可执行应用程序,即使依赖标记为 providedoptional,默认情况下仍会被包含以确保应用的完整性和可移植性。


网站公告

今日签到

点亮在社区的每一天
去签到