Spring boot实现热部署的两种方式详解
热部署是什么
大家都知道在项目开发过程中,常常会改动页面数据或者修改数据结构,为了显示改动效果,往往需要重启应用查看改变效果,其实就是重新编译生成了新的 Class 文件,这个文件里记录着和代码等对应的各种信息,然后 Class 文件将被虚拟机的 ClassLoader 加载。
而热部署正是利用了这个特点,它监听到如果有 Class 文件改动了,就会创建一个新的 ClaassLoader 进行加载该文件,经过一系列的过程,最终将结果呈现在我们眼前。
类加载机制
Java 中的类经过编译器可以把代码编译为存储字节码的 Class 文件,该 Class 文件存储了各种信息,最终要加载到虚拟机中运行使用。
类加载机制(摘自《深入理解 Java 虚拟机》)
虚拟机把描述类的数据从 Class 文件加载到内存中,并对数据进行校验、转换解析和初始化,最终形成可以被虚拟机直接使用的 Java 类型。
Spring Boot 实现热部署
Spring Boot 实现热部署很简单,我们使用上一章创建的项目 Springboot 创建简单的 web 交互应用 来演示。
- 使用 Spring Loaded
- 使用 spring-boot-devtools
springloaded
在 POM 文件中添加依赖
<build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>springloaded</artifactId> <version>1.2.6.RELEASE</version> </dependency> </dependencies> </plugin> </plugins> </build>
添加完毕,启动项目
Note
这次启动不能直接运行 main 方法了,需要使用
mvn spring-boot:run
启动,然后随意在代码中写一个 System.out.println("Hi")
,再次调用那个方法,会发现控制台会打印出 Hi。
spring-boot-devtools
添加 POM 文件依赖
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <optional>true</optional> <!-- 这个需要为 true 热部署才有效 --> </dependency>
然后还是使用 mvn spring-boot:run 启动项目,随意更改代码即可看到效果。
如果我们想指定让 devtools 监听指定文件夹,那么可以在 application.yml 配置
spring.devtools.restart.additional-paths=your path
,注意这里需要改成 yml 文件的格式。
Important(特别注意)
可能会有同学按照以上方法处理了都无效。
这里要特别注意下:由于热部署是监听 Class 文件的变化,它自身不会主动去编译 Java 文件,所以我们得在 Java 文件改动时,自动编译成 Class 文件,然后热部署工具创造的新的类加载器才会加载改变后的 Class 文件。
所以,如果你使用 IDEA 开发工具的话,记得要把自动编译打开。
如图打钩即可。
由于热部署的时候是产生了新的类加载器,我们的一个类可能在虚拟机中存在两个类,比如代码中就一个 User 类,但是虚拟机中会存在两个 User ,虽然是同一个 Class 文件,但是却是两个独立的类,这个要清楚。
由于第一次使用热部署,一开始遇到个很奇怪的问题,A instanceof A == false
,明明两个 A.getClass()
都一样,但结果就是 false,还问了几个朋友,表示都没遇到,后来当我把 devtools 依赖注释后,才正确执行。
如果有遇到类似问题的朋友,可以检查下是不是由于不同的 ClassLoader 造成的。
本系列所有代码已同步到 GitHub, 项目地址 github:sboot-learn,大家也可以通过本地进行下载。
总结
以上就是这篇文章的全部内容了,希望本文的内容对大家学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流,谢谢大家对我们的支持。