微服务框架之-Spring-Boot

113 阅读8分钟

Spring Boot可以轻松创建独立的, 具有产品水准的基于Spring的应用程序, 它做了大量的封装和接口的简化, 提倡用更少的配置, 和更少代码来创建Java Web 应用程序, 大大减轻了 Java 程序员的负担.

特点

  • 可以方便地创建独立的Spring应用程序
  • 直接嵌入Tomcat,Jetty或Undertow(无需部署WAR文件)
  • 提供预定义的初始POM以简化您的Maven配置
  • 每当可能时就自动配置Spring
  • 提供产线就绪的功能,如指标,健康检查和外部化配置
  • 绝对没有代码生成和不需要XML配置

Spring 命令行

Spring Boot 附带了一个命令行工具,如果你想快速使用Spring原型,可以使用它来运行Groovy脚本,Groovy有着类似Java的语法,却无需那么多的样板及胶水代码。

命令用途
run [options] [--] [args]执行spring groovy 脚本
test [options] [--] [args]执行 spring groovy 脚本测试
grab下载 spring groovy 脚本依赖到 ./repository 目录
jar [options] 从spring groovy 脚本创建一个自包含的可执行 jar 包
war [options] 从spring groovy 脚本创建一个自包含的可执行 war 包
install [options] Install dependencies to the lib/ext directory
uninstall [options] Uninstall dependencies from the lib/ext directory
init [options] [location]Initialize a new project using Spring Initializr (start.spring.io)
shellStart a nested shell

比如我想创建一个测试项目 hellospringboot

spring init -n hellospringboot -a hellospringboot -g com.github.walterfan -d=web,jpa,thymeleaf,mysql hellospringboot

Spring Boot 的精华

1. Starter 和 Auto Configuration

  • 烦人的依赖, 手工添加一个一个依赖包非常麻烦
  • 恼人的黑洞: Jar-A包含了v1.1的log4j, Jab-B 包含了 v1.2 的log4j, 当你引用了 log4j, 并用到了lo44j1.2的某个新方法, 你会惊讶地发现找不方法的错误
  • 麻烦的配置: 如果你用了 freemaker 作为页面的模板引擎, 你得手工在配置文件或配置类中设置

Starter 就是把这些烦人的事情打个包, 取个容易理解的名字, 提供一站式的服务, 不仅包括依赖管理, 还是一些自动配置, 帮你搞定这些琐事, 它通过一系列注解, 大大简化了配置, 提供嵌入式的 tomcat server , 可以 java 或 war 两种形式打包

  • 启动一个 SpringBoot Application 很简单
package com.example.myproject;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication // same as @Configuration @EnableAutoConfiguration @ComponentScan
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

}

配置

import org.springframework.boot.autoconfigure.*;
import org.springframework.boot.autoconfigure.jdbc.*;
import org.springframework.context.annotation.*;

@Configuration
@EnableAutoConfiguration(exclude={DataSourceAutoConfiguration.class})
public class MyConfiguration {
}
  • 什么是自动配置?

启用 Spring Application Context 的自动配置,试图猜测和配置你可能需要的bean。自动配置类通常基于你的类路径和你定义的bean来应用。例如,如果你的类路径上有tomcat-embedded.jar,你可能需要一个TomcatEmbeddedServletContainerFactory(除非你已经定义了你自己 EmbeddedServletContainerFactory bean)

自动配置尝试尽可能地智能化,并且随着您定义更多自己的配置而退出。您始终可以用 excludeName() 方法手动排除任何您不想应用的配置, 也可以通过spring.autoconfigure.exclude属性来排除它们。在用户定义的bean已经注册之后,总是应用自动配置。

Auto-configuration beans 是常规的 Spring Configuration beans. 它们是用 SpringFactoriesLoader 机制定位. 总的来说, auto-configuration beans 是 @Conditional beans, 多是用 @ConditionalOnClass 和 @ConditionalOnMissingBean 注解

package org.springframework.boot.autoconfigure;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.context.annotation.Import;

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import({EnableAutoConfigurationImportSelector.class})
public @interface EnableAutoConfiguration {
    String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";

    Class<?>[] exclude() default {};

    String[] excludeName() default {};
}

EnableAutoConfigurationImportSelector使用的是spring-core模块中的SpringFactoriesLoader#loadFactoryNames()方法,它的作用是在类路径上扫描META-INF/spring.factories文件中定义的类:

# Initializers
org.springframework.context.ApplicationContextInitializer=\
org.springframework.boot.autoconfigure.logging.AutoConfigurationReportLoggingInitializer

# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\
org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration,\
org.springframework.boot.autoconfigure.MessageSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.PropertyPlaceholderAutoConfiguration,\
org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration,\
org.springframework.boot.autoconfigure.data.JpaRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.MongoRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.redis.RedisAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration,\
org.springframework.boot.autoconfigure.jms.JmsTemplateAutoConfiguration,\
org.springframework.boot.autoconfigure.jmx.JmxAutoConfiguration,\
org.springframework.boot.autoconfigure.mobile.DeviceResolverAutoConfiguration,\
org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration,\
org.springframework.boot.autoconfigure.mongo.MongoTemplateAutoConfiguration,\
org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration,\
org.springframework.boot.autoconfigure.reactor.ReactorAutoConfiguration,\
org.springframework.boot.autoconfigure.security.SecurityAutoConfiguration,\
org.springframework.boot.autoconfigure.security.FallbackWebSecurityAutoConfiguration,\
org.springframework.boot.autoconfigure.thymeleaf.ThymeleafAutoConfiguration,\
org.springframework.boot.autoconfigure.web.EmbeddedServletContainerAutoConfiguration,\
org.springframework.boot.autoconfigure.web.DispatcherServletAutoConfiguration,\
org.springframework.boot.autoconfigure.web.ServerPropertiesAutoConfiguration,\
org.springframework.boot.autoconfigure.web.MultipartAutoConfiguration,\
org.springframework.boot.autoconfigure.web.HttpMessageConvertersAutoConfiguration,\
org.springframework.boot.autoconfigure.web.WebMvcAutoConfiguration,\
org.springframework.boot.autoconfigure.websocket.WebSocketAutoConfiguration

实际上这就是Spring Boot会自动配置的一些对象,例如前面提到的Web框架由EmbeddedServletContainerAutoConfiguration, DispatcherServletAutoConfiguration, ServerPropertiesAutoConfiguration等配置完成,而DataSource的自动配置则是由DataSourceAutoConfiguration完成的

2. Develop tools

3. Spring Boot Actuator

IDDescription
auditeventsExposes audit events information for the current application.

Metrics

{
    "counter.status.200.root": 20,
    "counter.status.200.metrics": 3,
    "counter.status.200.star-star": 5,
    "counter.status.401.root": 4,
    "gauge.response.star-star": 6,
    "gauge.response.root": 2,
    "gauge.response.metrics": 3,
    "classes": 5808,
    "classes.loaded": 5808,
    "classes.unloaded": 0,
    "heap": 3728384,
    "heap.committed": 986624,
    "heap.init": 262144,
    "heap.used": 52765,
    "nonheap": 0,
    "nonheap.committed": 77568,
    "nonheap.init": 2496,
    "nonheap.used": 75826,
    "mem": 986624,
    "mem.free": 933858,
    "processors": 8,
    "threads": 15,
    "threads.daemon": 11,
    "threads.peak": 15,
    "threads.totalStarted": 42,
    "uptime": 494836,
    "instance.uptime": 489782,
    "datasource.primary.active": 5,
    "datasource.primary.usage": 0.25
}

spring boot 的启动过程

Spring Boot 的启动过程是一个非常完整的生命周期管理过程,从准备环境、加载配置、初始化上下文到启动 Web 服务器,再到启动完成后等待请求处理。通过这种架构,Spring Boot 实现了高度的自动化和便捷的配置管理,使开发者能够快速构建、配置和启动应用。 启动过程涉及了多个组件的初始化与自动配置,但总体上可以分为几个主要步骤。从高层次来看,启动过程包括以下步骤:

1. 准备阶段:启动类加载器与设置启动环境

Spring Boot 应用程序从 main 方法启动。典型的启动类如下:

@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}
  • SpringApplication.run() 方法启动应用。这是 Spring Boot 应用的核心入口。
  • SpringApplication 用于引导和配置 Spring 应用的上下文。

主要执行步骤:

  • 检查运行环境,创建或识别 Spring 的 ApplicationContext。
  • 通过 SpringApplication 的静态初始化代码加载默认的配置(例如 application.properties、application.yml)。

2. 创建 SpringApplication 实例

在 SpringApplication.run() 中,首先创建 SpringApplication 实例:

  • 设置应用类型:Spring Boot 会根据类路径中的依赖自动判断应用是 Servlet 应用还是 Reactive 应用。
  • 配置 ApplicationContext:选择合适的 ApplicationContext 类型。Web 应用默认使用 AnnotationConfigServletWebServerApplicationContext,非 Web 应用则使用 AnnotationConfigApplicationContext。
  • 加载应用程序的初始化类:SpringApplication 会找到实现了 ApplicationContextInitializer 接口的所有类。

3. 调用 run() 方法****

进入 run() 方法后,Spring Boot 执行启动的主要流程:

3.1 创建并配置 Environment

SpringApplication 会创建一个 Environment 对象,它表示当前应用的运行环境,包含系统属性、环境变量、命令行参数等。主要步骤包括:

  • 加载外部配置:例如 application.properties、application.yml 文件。
  • 将命令行参数绑定到 Environment 中,允许在启动时传入参数来覆盖默认配置。

3.2 创建 ApplicationContext

SpringApplication 根据应用类型创建合适的 ApplicationContext,并将 Environment 与 ApplicationContext 进行关联。ApplicationContext 是 Spring 的核心容器,用于管理 Bean 生命周期与依赖注入等。

3.3 准备 ApplicationContext****

在 ApplicationContext 初始化过程中,Spring Boot 会加载 Bean、执行配置文件并完成自动配置。

  • 加载并注册所有 Bean:@SpringBootApplication 注解会触发 @ComponentScan 扫描,注册应用中的所有组件(例如 @Component、@Service、@Repository 等)。

  • 执行自动配置:Spring Boot 自动配置通过 @EnableAutoConfiguration 注解激活,加载自动配置类并按条件初始化相关 Bean。比如,在类路径中有 spring-boot-starter-web 依赖时,Spring Boot 会自动配置 DispatcherServlet、EmbeddedWebServer 等 Web 相关的组件。

3.4 加载 ApplicationRunner 和 CommandLineRunner

• ApplicationRunner 和 CommandLineRunner 是 Spring Boot 提供的两个接口,它们允许在 Spring 应用启动后立即执行一些代码。

• CommandLineRunner 接收 String 类型的参数,ApplicationRunner 接收 ApplicationArguments 对象。

3.5 初始化生命周期事件广播

Spring Boot 使用 SpringApplicationRunListeners 监听应用启动的不同阶段并广播事件。这些事件包括:

• ApplicationStartingEvent:应用开始启动时发布。

• ApplicationEnvironmentPreparedEvent:Environment 准备完成时发布。

• ApplicationContextInitializedEvent:ApplicationContext 准备完成时发布。

• ApplicationPreparedEvent:ApplicationContext 加载完成,Bean 已经定义,但未实例化时发布。

• ApplicationStartedEvent:应用启动完成且所有 Bean 已实例化时发布。

• ApplicationReadyEvent:应用完全启动并准备好处理请求时发布。

• ApplicationFailedEvent:应用启动失败时发布。

开发者可以通过实现 ApplicationListener 来监听这些事件并执行相应的操作。

4. 刷新 ApplicationContext

在 ApplicationContext 完成准备后,Spring Boot 会调用 ApplicationContext 的 refresh() 方法。这一步非常重要,因为它会完成以下几件事:

  • 初始化所有单例 Bean。
  • 扫描并注册所有 Bean,并进行依赖注入。
  • 注册 BeanPostProcessor 和 BeanFactoryPostProcessor,实现 Bean 的进一步初始化。

这一步完成后,应用的主配置类、所有依赖的 Bean 和相关的自动配置都已初始化并加载。

5. 启动 Web 服务器(Web 应用特有)

如果是 Web 应用,Spring Boot 会启动内嵌的 Web 服务器(如 Tomcat、Jetty 或 Undertow),并将 DispatcherServlet 注册到 Servlet 上下文中:

  • 内嵌服务器实例化并启动:比如,TomcatServletWebServerFactory 会启动嵌入式 Tomcat。

  • 配置 DispatcherServlet:Spring Boot 自动为 Web 应用注册一个 DispatcherServlet 来处理 HTTP 请求。

6. 调用 CommandLineRunner 和 ApplicationRunner

当 Spring 应用启动完成后,Spring Boot 会检查并执行所有实现了 CommandLineRunner 和 ApplicationRunner 的 Bean。

  • 如果应用中定义了多个 CommandLineRunner 或 ApplicationRunner,可以通过 @Order 注解控制它们的执行顺序。

7. 应用进入运行状态

到这里,Spring Boot 应用已完全启动,所有 Bean 已初始化并准备好接收请求。此时,应用进入运行状态,等待处理客户端请求。

8. 关闭应用程序(Graceful Shutdown)

当应用程序接收到关闭信号(例如 SIGTERM),Spring Boot 会执行关闭过程:

  • 调用 DisposableBean destroy() 方法:会释放资源和执行 Bean 的清理操作。
  • 关闭 Web 服务器:如果应用是 Web 应用,Spring Boot 会优雅地关闭 Web 服务器并等待当前请求处理完成。
  • 发布 ContextClosedEvent 事件:让监听器可以响应关闭事件。
  • 销毁 ApplicationContext:销毁所有 Bean,并清理 ApplicationContext 中的资源。

参考资料