阅读(2215) (0)

Micronaut 重载

2023-02-23 13:57:40 更新

重新加载(或“热加载”)是指在检测到源文件发生更改时框架重新初始化类(和应用程序的一部分)。

由于 Micronaut 优先考虑启动时间,并且大多数 Micronaut 应用程序可以在几秒钟内启动,因此通常可以通过在进行更改时重新启动应用程序来获得高效的工作流程;例如,通过在 IDE 中运行测试类。

但是,为了让您的更改自动重新加载,Micronaut 支持自动重启和使用第三方重新加载代理。

自动重启

在JVM上实现类重载的方式有很多种,各有优缺点。以下是在不重启 JVM 的情况下实现重新加载的可能方法:

  • JVM Agents - 可以使用 JRebel 之类的 JVM 代理,但是这些代理可能会产生异常错误,可能不支持所有 JDK 版本,并且可能导致缓存类或陈旧类。
  • ClassLoader Reloading - 基于 ClassLoader 的重新加载是大多数 JVM 框架使用的流行解决方案;然而,如果使用不正确的类加载器,它又会导致缓存类或陈旧类、内存泄漏和奇怪的错误。
  • Debugger HotSwap - Java 调试器支持在运行时热交换更改,但仅支持少数用例。

鉴于现有解决方案存在的问题以及 JVM 中缺乏重新加载更改的内置方法,最安全和最佳的重新加载解决方案,也是 Micronaut 团队推荐的解决方案,是通过第三方工具使用自动应用程序重启。

Micronaut 的启动时间很快,自动重启会导致一个干净的状态,而不会出现潜在的难以调试的问题或内存泄漏。

Maven 重启

要使用 Maven 自动重启应用程序,请使用 Micronaut Maven 插件(创建新 Maven 项目时默认包含)并运行以下命令:

使用 Micronaut Maven 插件

$ ./mvnw mn:run

每次更改类时,插件都会自动重新启动服务器。

Gradle 重启

使用 Micronaut Gradle 插件时,可以通过 -t 标志激活 Gradle 对连续构建的支持来激活 Gradle 自动重启:

使用 Gradle 自动重启

./gradlew run -t

每次您对类或资源进行更改时,Gradle 都会重新编译并重新启动应用程序。

JRebel

JRebel 是一个专有的重新加载解决方案,它涉及一个代理库,以及复杂的 IDE 支持。 JRebel 文档包括 IDE 集成和使用的详细步骤。在本节中,我们将展示如何为 Maven 和 Gradle 项目安装和配置代理。

使用 CLI

如果您使用 Micronaut CLI 创建项目,请提供 jrebel 功能以在您的项目中预配置 JRebel 重新加载。请注意,您需要安装 JRebel 并在 gradle.properties 文件(对于 Gradle)或 pom.xml(对于 Maven)中提供代理的正确路径。必要的步骤如下所述。

$ mn create-app my-app --features jrebel

安装/配置 JRebel 代理

安装 JRebel 的最简单方法是从 JRebel 下载页面下载“独立”安装包。将下载的文件解压到方便的位置,例如 ~/bin/jrebel

安装目录包含一个带有代理文件的 lib 目录。对于基于您的操作系统的适当代理,请参见下表:

表 1. JRebel Agent
OS Agent

Windows 64-bit JDK

[jrebel directory]\lib\jrebel64.dll

Windows 32-bit JDK

[jrebel directory]\lib\jrebel32.dll

Mac OS X 64-bit JDK

[jrebel directory]/lib/libjrebel64.dylib

Mac OS X 32-bit JDK

[jrebel directory]/lib/libjrebel32.dylib

Linux 64-bit JDK

[jrebel directory]/lib/libjrebel64.so

Linux 32-bit JDK

[jrebel directory]/lib/libjrebel32.so

记下相应代理的路径,并将值添加到您的项目构建中。

Gradle

将路径添加到 gradle.properties(必要时创建文件),作为 rebelAgent 属性。

gradle.properties

#Assuming installation path of ~/bin/jrebel/
rebelAgent= -agentpath:~/bin/jrebel/lib/libjrebel64.dylib

将适当的 JVM arg 添加到 build.gradle(如果使用 CLI 功能则不需要)

run.dependsOn(generateRebel)
if (project.hasProperty('rebelAgent')) {
    run.jvmArgs += rebelAgent
}

您可以使用 ./gradlew run 启动应用程序,它将包含代理。请参阅有关 Gradle 重新加载或 IDE 重新加载的部分以设置重新编译。

Maven

相应地配置 Micronaut Maven 插件:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <!-- ... -->
  <build>
    <plugins>
      <!-- ... -->
      <plugin>
        <groupId>io.micronaut.build</groupId>
        <artifactId>micronaut-maven-plugin</artifactId>
          <configuration>
            <jvmArguments>
              <jvmArgument>-agentpath:~/bin/jrebel/lib/jrebel6/lib/libjrebel64.dylib</jvmArgument>
            </jvmArguments>
          </configuration>
      </plugin>
      <plugin>
        <groupId>org.zeroturnaround</groupId>
        <artifactId>jrebel-maven-plugin</artifactId>
        <version>1.1.10</version>
        <executions>
          <execution>
            <id>generate-rebel-xml</id>
            <phase>process-resources</phase>
            <goals>
              <goal>generate</goal>
            </goals>
          </execution>
        </executions>
      </plugin>
      <!-- ... -->
    </plugins>
  </build>
</project>

使用 Gradle 重新编译

Gradle 支持连续构建,让您运行的任务将在源文件更改时重新运行。要将其与重新加载代理(如上所述配置)一起使用,请正常运行应用程序(使用代理),然后在启用连续模式的单独终端中运行重新编译任务。

运行应用

$ ./gradlew run

运行重新编译

$ ./gradlew -t classes

每次修改源文件时都会重新运行类任务,从而允许重新加载代理获取更改。

使用 IDE 重新编译

如果您使用不支持自动重新编译文件更改的构建工具(如 Maven),您可以使用您的 IDE 结合重新加载代理(如上述部分中配置)重新编译类。

IntelliJ

不幸的是,IntelliJ 没有适用于正在运行的应用程序的自动重建选项。但是,您可以使用 CMD-F9 (Mac) 或 CTRL-F9 (Windows/Linux) 触发项目的“重建”。

Eclipse

在“项目”菜单下,选中“自动构建”选项。每当文件更改保存到磁盘时,这将触发项目的重新编译。