如何在 Spring Boot 中选择性地升级依赖项? (示例案例:Spring Data)

Posted

技术标签:

【中文标题】如何在 Spring Boot 中选择性地升级依赖项? (示例案例:Spring Data)【英文标题】:How to selectively upgrade a dependency in Spring Boot? (sample case: Spring Data) 【发布时间】:2018-02-08 14:01:14 【问题描述】:

我使用 Spring Boot (1.4.1) 的 Spring Data JPA starter。它包含 Spring Data JPA 1.10.3。但是,我需要使用此版本 spring 数据中尚不存在的 @DomainEvents 注释。当我尝试添加最新版本的 Spring Data JPA 时,我的应用程序运行时出现错误。

我的 pom 示例:

<parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.4.1.RELEASE</version>
        <relativePath/>
</parent>

<dependencies>
        ...
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        ...
</dependencies>

当我尝试像这样添加最新版本的 Spring Data JPA 时:

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.data</groupId>
            <artifactId>spring-data-jpa</artifactId>
            <version>1.11.6.RELEASE</version>
        </dependency>
    </dependencies>
</dependencyManagement>

我在启动我的应用程序时遇到错误。像这样的错误:

Caused by: java.lang.NoSuchMethodException: org.springframework.data.jpa.repository.support.JpaRepositoryFactoryBean.<init>()
  at java.lang.Class.getConstructor0(Class.java:3082) ~[na:1.8.0_121]
  at java.lang.Class.getDeclaredConstructor(Class.java:2178) ~[na:1.8.0_121]
  at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:80) ~[spring-beans-4.3.3.RELEASE.jar:4.3.3.RELEASE]
  ... 53 common frames omitted

如何使用较新版本的 Spring Data JPA?我的应用中需要@DomainEvents。谢谢!

【问题讨论】:

您的意思是您需要更新版本的spring-data-jpa?你说你是 Spring boot 1.4.1,它正在拉它包含 1.10.3,但你正在转向更新的版本。 您可以尝试升级发布系列,但是您可能会遇到问题,因为它还取决于较新的 Spring 版本,可能无法(完全)使用您的 JPA 版本/实现等。 真的。我没有考虑。谢谢。 【参考方案1】:

这里有多种给猫剥皮的方法,它们都有不同的优缺点:

选项 1:升级到较新版本的 Boot

总体而言,最安全的方法是升级到更新版本的 Spring Boot。我们通常建议使用当前主要版本中的最新次要版本。在您的情况下,1.5 是最新的次要版本,因此我们建议升级到该版本(当前为 1.5.6)。这通常只需更改您使用的父 pom 的版本号即可实现。

<parent>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-parent</artifactId>
  <version>1.5.6.RELEASE</version>
</parent>

优点

您将自动将所有引导管理的依赖项升级到它们的最新兼容版本。这是可取的,因为这将确保您获得第三方依赖项中安全更新的最新修复

缺点

小版本升级可能需要您稍微更改配置或 API 中的内容,以防您依赖应用程序代码中的第三方 API。 Boot 中的小版本升级通常非常小心,不会在第三方库中引入重大更改,但不幸的是,并非所有升级都遵循语义版本控制。但是,如果您有一个不错的测试套件,应该很容易发现您是否会遇到问题。建议查看 release notes,因为它们通常包含迁移指南。

选项 2:单独升级依赖项

前一种方法的替代方法是保持您当前的引导版本,但有选择地升级第三方依赖项。最好的方法是检查spring-boot-dependencies 中存在哪些版本占位符。然后你只需要在你的项目中重新声明属性并调整版本。对于 Spring Data,那就是:

<properties>
  <spring-data-releasetrain.version>Ingalls-SR6<spring-data-releasetrain.verion>
</properties>

如果是 Spring Data,您将在此处一次升级整个发布系列,这样如果您只升级一个模块,就不会在内部遇到 Spring Data 模块之间的不兼容问题。这是建议“按属性升级”而不是在较新版本中明确重新声明依赖项的主要原因之一(在某些情况下,这仍然是最后的手段)。

优点

升级操作更具选择性。与以前的方法相比,您不会冒着遇到无关依赖项的升级问题的风险。

缺点

它可能不起作用! - 有时依赖项会更改 Boot 的自动配置在次要版本中依赖的一些内部 API。这可能会导致自动配置在启动时不起作用,您可以尝试通过明确排除自动配置并编写手动配置来替换它。

建议步骤

在实践中我通常会尝试以下步骤:

    使用选项 1 进行升级时影响尽可能小。如果成功:完成。 如果这会导致问题,请评估将自动配置替换为手动配置的难度(通常需要对 Boot 有一些了解和经验。如果成功:完成。 使用选项 2 升级到较新版本的 Boot 并评估这对您的应用程序代码的影响。

2 和 3 可能可以互换,具体取决于您个人的偏好或您为团队定义的依赖项升级策略。

一般来说,密切关注 Boot 版本并定期尝试将项目干升级到较新版本是一个好主意,但不一定要将升级发布到生产环境。这使您可以评估升级的风险并估计需要进行的工作量。 避免升级基本上只会让升级更加痛苦,但是,有时由于政治原因或升级在新版本中遇到问题,无法立即进行升级。

【讨论】:

谢谢。在发布序列级别升级(例如 - spring-data)也会同时升级多个客户端库。并非总是可以同时升级所有解决方案,以支持任何/某些其他提供商的升级。例如spring-boot.2.0.X 支持ElasticSearch 5.5..XKafka 1.0.X;现在如果我需要将Kafka升级到2.0.X,则必须使用与ElasticSearch 6.0.X兼容的spring-boot 2.1.X;但我可能不需要ElasticSearch 版本升级。我们如何处理此类案件?选择性覆盖版本是有风险的,不是吗? 是的。您可能可以升级到 Boot 2.1,但将 Spring Data 降级到 Kay 并进行测试。根据您正在使用的模块,您可能会看到这是有效的,因为我们正在努力尽量减少对 Boot 的 API 更改。在某些情况下,我们没有太多选择,因为数据库客户端会大幅更改 API。

以上是关于如何在 Spring Boot 中选择性地升级依赖项? (示例案例:Spring Data)的主要内容,如果未能解决你的问题,请参考以下文章

记一次升级Spring Boot 版本遇到的问题.

升级后的 Spring Boot Oauth2 自动配置周期

spring boot 2.0之使用spring boot

升级到 Spring Boot 2.5.1 和 Spring Cloud 2020.0.3 时,Netflix zuul 和 Ribbon 的 Maven 依赖项有啥不同吗

Spring Boot版本升级-在aws elastic beanstalk中部署时出现mysql错误

spring boot 2-日志