Springboot开发记录

Posted by     "zengchengjie" on Thursday, June 4, 2020

概念

springboot相关概念

点击阅读官方文档

springboot最新版2.6.4参考文档

springboot quick start

特征

按照官方文档说法,有如下几点特征

我们的主要目标是:

  • 为所有 Spring 开发提供从根本上更快且可广泛访问的入门体验。
  • 开箱即用,但随着需求开始偏离默认值,请迅速摆脱困境。
  • 提供一系列大型项目通用的非功能特性(例如嵌入式服务器、安全性、指标、健康检查和外部化配置)。
  • 绝对没有代码生成,也不需要 XML 配置。

用我们自己的体验来说,翻译成直白的话,则是:用起来很简单,不用配置xml了,三方库的支持很多,自身的生态完善(spring data、spring cloud、spring security、spring session、spring shell等等),总而言之,用我这套就够了,啥都给你整好了,那么springboot究竟有什么样的好处,足以令其流行并受到多数公司的推崇呢?我们来通过实践一步一步揭开它的神秘面纱。

开箱即用

首先,对于大多数初学者来说,这个是很重要的一点,比如你写一个helloWord,你只需要创建一个maven的pom.xml依赖:

<?xml version="1.0" encoding="UTF-8"?>
<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.example</groupId>
    <artifactId>myproject</artifactId>
    <version>0.0.1-SNAPSHOT</version>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.6.4</version>
    </parent>
  
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    </dependencies>

    <!-- Additional lines to be added here... -->

</project>

并编写代码:

@RestController
@EnableAutoConfiguration
public class MyApplication {

    @RequestMapping("/")
    String home() {
        return "Hello World!";
    }

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

}

然后run就可以了,你甚至不需要指定server的端口(默认8080),当然,通常情况下,我们的接口和我们的main方法是分开管理的,以此避免代码耦合,一般如下:

main方法:

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

接口:

@RestController
@RequestMapping("/test")
public class HelloWorldApi {
    @PostMapping("/")
    String home() {
        return "Hello World!";
    }
}

然后run这个main方法就行了,对于长期使用springboot的小伙伴也许觉得习以为常,但当你用过多个框架或者其他语言之后,很多人会惊呼:发生了什么,为什么这就启动起来了呢?没有看到注册api接口,没有看到服务器端口配置,甚至没有看到日志配置就能打印详细的日志。其实,这一切是springboot框架为我们做的事,为了简化开发和自动配置,spring很好的利用了ioc和aop这两大思想,开发出了一套开箱即用的框架。

这一切的开始,我们需要从我们使用的这几个注解开始理解

@RestController 和 @RequestMapping 注解

MyApplication我们类的第一个注释是@RestController. 这称为构造型注释。它为阅读代码的人和 Spring 提供了类扮演特定角色的提示。在这种情况下,我们的类是一个 web @Controller,因此 Spring 在处理传入的 Web 请求时会考虑它。

@RequestMapping注释提供“路由”信息。它告诉 Spring 任何带有该/路径的 HTTP 请求都应该映射到该home方法。注释告诉 Spring将@RestController结果字符串直接呈现给调用者。

和注释是 Spring MVC 注释@RestController@RequestMapping它们不是特定于 Spring Boot)。有关详细信息,请参阅 Spring 参考文档中的MVC 部分

@EnableAutoConfiguration 注解

第二个类级别的注释是@EnableAutoConfiguration. 这个注解告诉 Spring Boot 根据你添加的 jar 依赖来“猜测”你想如何配置 Spring。由于spring-boot-starter-web添加了 Tomcat 和 Spring MVC,自动配置假定您正在开发 Web 应用程序并相应地设置 Spring。

启动器和自动配置

自动配置旨在与“启动器”很好地配合使用,但这两个概念并没有直接联系。您可以自由选择启动器之外的 jar 依赖项。Spring Boot 仍然尽力自动配置您的应用程序。

main方法

我们应用程序的最后一部分是main方法。这是一种遵循应用程序入口点的 Java 约定的标准方法。我们的 main 方法通过调用委托给 Spring Boot 的SpringApplicationrunSpringApplication引导我们的应用程序,启动 Spring,然后启动自动配置的 Tomcat Web 服务器。我们需要将MyApplication.class作为参数传递给该run方法,以判断SpringApplication哪个是主要的 Spring 组件。该args数组也被传递以公开任何命令行参数

当然,这仅仅是springboot的冰山一角,寥寥几个注解只是作为一个指引者让我们关注到springboot的特别之处,所以我们需要先了解一下springboot的用到的两个关键思想:ioc和aop

IOC和AOP

Spring框架包含众多模块,如Core、Testing、Data Access、Web Servlet等,其中Core是整个Spring框架的核心模块。Core模块提供了IoC容器、AOP功能、数据绑定、类型转换等一系列的基础功能,而这些功能以及其他模块的功能都是建立在IoC和AOP之上的,所以IoC和AOP是Spring框架的核心。 IoC(Inversion of Control)是控制反转的意思,这是一种面向对象编程的设计思想。

在不采用这种思想的情况下,我们需要自己维护对象与对象之间的依赖关系,很容易造成对象之间的耦合度过高,在一个大型的项目中这十分的不利于代码的维护。IoC则可以解决这种问题,它可以帮我们维护对象与对象之间的依赖关系,降低对象之间的耦合度。

说到IoC就不得不说DI(Dependency Injection),DI是依赖注入的意思,它是IoC实现的实现方式,就是说IoC是通过DI来实现的。由于IoC这个词汇比较抽象而DI却更直观,所以很多时候我们就用DI来代替它,在很多时候我们简单地将IoC和DI划等号,这是一种习惯。而实现依赖注入的关键是IoC容器,它的本质就是一个工厂。

AOP(Aspect Oriented Programing)是面向切面编程思想,这种思想是对OOP的补充,它可以在OOP的基础上进一步提高编程的效率。简单来说,它可以统一解决一批组件的共性需求(如权限检查、记录日志、事务管理等)。在AOP思想下,我们可以将解决共性需求的代码独立出来,然后通过配置的方式,声明这些代码在什么地方、什么时机调用。当满足调用条件时,AOP会将该业务代码织入到我们指定的位置,从而统一解决了问题,又不需要修改这一批组件的代码。

springboot的起步依赖

Spring Boot 将日常企业应用研发中的各种场景都抽取出来,做成一个个的 starter(启动器),starter 中整合了该场景下各种可能用到的依赖,用户只需要在 Maven 中引入 starter 依赖,SpringBoot 就能自动扫描到要加载的信息并启动相应的默认配置。

starter 提供了大量的自动配置,让用户摆脱了处理各种依赖和配置的困扰。所有这些 starter 都遵循着约定成俗的默认配置,并允许用户调整这些配置,即遵循“约定大于配置”的原则。

那么我们看构建的项目的pom.xml文件中的starter配置。

<dependency> 
  <groupid>org.springframework.boot</groupid>
 <artifactid>spring-boot-starter-web</artifactid>
</dependency>

以 spring-boot-starter-web 为例,它能够为提供 Web 开发场景所需要的几乎所有依赖,因此在使用 Spring Boot 开发 Web 项目时,只需要引入该 Starter 即可,而不需要额外导入 Web 服务器和其他的 Web 依赖。

有时在引入starter时,我们并不需要指明版本(version),这是因为starter版本信息是由 spring-boot-starter-parent(版本仲裁中心) 统一控制的。

springboot的启动流程

当Spring Boot项目创建完成后会默认生成一个Application的入口类,这个类中的mn方法可以启动Spring Boot项目,在mn方法中,通过SpringApplication的静态方法,即run方法进行SpringApplication的实例化操作,然后再针对实例化对象调用另外一个run方法来完成整个项目的初始化和启动。

SpringApplication调用的run方法重点做了以下操作:

  • 获取监听器参数配置

  • 打印Banner信息

  • 创建并初始化容器

  • 监听器发送通知

    SpringApplication实例化过程中相对重要的配置:

  • 项目启动类 SpringbootDemoApplication.class 设置为属性存储起来 this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));

  • 设置应用类型是 SERVLET 应用还是 REACTIVE 应用 this.webApplicationType = WebApplicationType.deduceFromClasspath(); - 设置初始化器(Initializer),最后会调用这些初始化器

  • 所谓的初始化器就是 org.springframework.context.ApplicationContextInitializer 的实现类,在 Spring 上下文被刷新之前进行初始化的操作 setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));

  • 设置监听器(Listener) setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));

  • 初始化 mnApplicationClass 属性:用于推断并设置项目 mn()方法启动的主程序启动类 this.mnApplicationClass = deduceMnApplicationClass();

相关实践

集成Redis

集成kafka

配置优化

性能优化