Spring Boot魔术背后的剖析

18-10-24 banq
         

随着微服务架构和云计算的出现,对工件部署的新方法的需求日益增长:独立的Java应用程序。在很短的时间内, Spring Boot 已成为该领域的领先技术。其优势包括:

  1. 有自己意见的观点 - 这意味着它在你的位置做了很多工作;
  2. 一个非常快速的项目启动:依赖关系按主题分组为所谓的“启动器”
  3. 可执行jar:生成的工件是可执行的JAR(或更好的Uber JAR);

我对Spring Boot的看法

从我的角度来看,这是“控制反转”实现的一个例子 - 通常,你选择一组库,然后尝试将它们配置为一起工作,但在这种情况下,你将控制权交给了需要注意的框架配置。

应用程序启动时,框架会检测类路径的依赖关系并尝试对其进行配置。例如,当Spring Boot 在类路径上检测到 Hibernate jar时,它会为您配置数据源,或者当找到Spring MVC jar时,它会配置Dispatcher Servlet。启用自动配置非常简单; 只需使用自动配置注释您的主配置类,可以通过使用@SpringBootApplication或注释您的主类来启用@EnableAutoConfiguration。

自动配置应用程序所需的所有逻辑都由spring-boot-autoconfigure库处理,该库包含打包以执行特定配置逻辑的所有类。

此外,通过在类路径上提供名为application.properties(或application.yaml)的文件,实现了一种极端的“约定优于配置”方法来定制自动配置的几乎每个方面。

在此文件中,您可以将自动配置的特定方面控制为服务器端口:

server.port=8090

并且,可排除特定类如下所示:

spring.autoconfigure.exclude=org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration.

    

快速项目启动

大多数情况下,要启动Spring Boot项目,只需转到start.spring.io,选择要使用的技术,然后下载一个zip文件,其项目结构为Maven或Gradle项目。

请注意,我写的是“技术”,而不是“库”;这是因为你可以说:“我想要一个带有安全性和JPA的Web应用程序”,Spring将为您选择合适的库。

在我看来,最不平凡的事情不是启动一个项目这么容易的事实,而是Spring以如此优雅的方式完成它的方式。

我们的想法是将一组有用且集中的库分组到一个多模块项目中,然后将其作为依赖项包含在内。

例如,当您选择“Web”选项时,start.spring.io会添加:

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>

下面只是一个多模块项目,它收集运行包含嵌入式Tomcat的Web应用程序所需的所有库:

<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-core</artifactId>
</dependency>

这种方法最显着的好处之一是您不必担心库版本兼容性 - 启动器将此作为保证。

可执行的Jar

将配置检测和启动器放在一起,唯一缺少的是分发更方便的方法。Spring Boot通过将整个项目打包为Uber JAR来解决这个问题。

Uber JAR是一个常规JAR,其中包含所需的所有依赖项。这是使用:

  1. spring-boot-maven-plugin:你可以在pom的插件plugins部分找到它;
  2. maven-shade-plugin:它是spring-boot-starter-parent提供的,它创造了有效的Uber Jar。

特别是maven-shade-plugin负责打包依赖,并通过变换器配置 - 特定文件,如:

  1.  ManifestResourceTransformer将MANIFEST.MF处理到META-INF下;
  2. ServicesResourceTransformer将服务提供者配置文件放入META-INFservices 下。

以下是与Spring Boot Loader兼容的JAR结构的示例:

+-META-INF
 |  +-MANIFEST.MF
 +-org
 |  +-springframework
 |     +-boot
 |        +-loader
 |           +- Main-Class
 +-BOOT-INF
    +-classes
    |  +- Start-Class
    +-lib
       +-dependency.jar

为了使其可执行,使用以下属性初始化META-INF\MANIFEST.MF文件:

Main-Class: org.springframework.boot.loader.JarLauncher
Start-Class: com.yourcompany.MainCOnfigurationCLass
Spring-Boot-Classes: BOOT-INF/classes/
Spring-Boot-Lib: BOOT-INF/lib/

当应用程序启动时 - 使用

java -jar application.jar 

- META-INF\MANIFEST.MF被读取。在这里,org.springframework.boot.loader.JarLauncher作为主类加载 - 它的工作是加载以下内容:

  1. 将库放入BOOT-INF/lib
  2. 将应用程序类放入BOOT-INFclasses。

BOOT-INF\classes包含启动类- 一个带注释@SpringBootApplication的类实际上启动并引导Spring应用程序。

结论

Spring Boot是一个完善架构的一个非凡例子:它完成特定任务,使用现代方法,并提出所有热门话题的解决方案。

如果有人发现Spring Boot限制太多,那是因为它的功能在于其配置发现及其依赖关系的管理 - 这可能会迫使用户失去控制权。例如,使用不同的父POM而不是spring-boot-starter-parent并不是一件容易的事。

在我看来,Spring Boot必须被视为一个框架,目标作为标准化的工具集合而不是实用程序库。如果你不使用Spring Boot,您创建一个类似Spring Boot的应用程序(即本机云Java应用程序)。

如果以这种方式思考,那么您可以享受Spring Boot方式来做事并从中获得最大收益!快乐的编码!