一、Springboot简介
1.1 Springboot是什么
Spring Boot就是Spring,它做了那些没有它你也会去做的Spring Bean配置。它使用“习惯优于配置”(项目中存在大量的配置,此外还内置了一个习惯性的配置,让你无需手动进行配置)的理念让你的项目快速运行起来。使用Spring Boot很容易创建一个独立运行(运行jar,内嵌Servlet容器)、准生产级别的基于Spring框架的项目,使用Spring Boot你可以不用或者只需要很少的Spring配置
1.2 Springboot的特点
(1)创建独立的Spring应用程序
(2)直接嵌入Tomcat,Jetty或Undertow,无需部署WAR文件
(3)提供推荐的基础POM文件来简化Apache Maven配置
(4)尽可能的根据项目依赖来自动配置Spring框架
(5)提供生产就绪型功能,如指标,运行状况检查和外部配置
(6)绝对没有代码生成和对XML没有要求配置
1.3 Springboot核心
(1)自动配置:针对很多Spring应用程序常见的应用功能,Spring Boot能自动提供相关配置
(2)起步依赖:告诉Spring Boot需要什么功能,它就能引入需要的库。
(3)命令行界面:这是Spring Boot的可选特性,借此你只需写代码就能完成完整的应用程序,无需传统项目构建。
(4)Actuator:让你能够深入运行中的Spring Boot应用程序,一探究竟。
1.4 Springboot的优点
(1)spring boot可以支持开发人员快速的开发出restful风格的微服务架构;
(2)spring boot自动化确实方便,做微服务再合适不过了,单一jar包部署和管理都非常方便。
(3)spring boot要解决的问题, 精简配置是一方面, 另外一方面是如何方便的让spring生态圈和其他工具链整合(比如Redis,email,elasticsearch)。
1.5 Springboot的优点
(1)需要非常了解Spring Boot的核心技术原理,不然一旦遇到问题就很棘手。因为什么东西都集成了,自动配置化。这样,需要对配置信息非常熟悉,要找起问题来不是很容易。
(2)从原始Spring项目很难平滑迁移至 Spring Boot 框架上来,因为有些历史老旧的 XML 配置无法通过 Java 来配置,还需要额外的 XML 文件就不是很完美。再比如,之前是独立的 Tomcat,什么参数都在线上配置好了,你改为内置的 Tomcat 就会遇到很多问题。
二、Springboot常用注解
2.1 @SpringBoot/spring
@SpringBootApplication:
包含
@Configuration、@EnableAutoConfiguration、@ComponentScan通常用在主类上;
2.2 @RestController
RestController被称为一个构造型(stereotype)注解。它为阅读代码的开发人员提供建议。对于Spring,该类扮演了一个特殊角色。它继承自@Controller注解。4.0之前的版本,spring MVC的组件都使用@Controller来标识当前类是一个控制器servlet。使用这个特性,我们可以开发REST服务的时候不需要使用@Controller而专门的@RestController。
2.3 @Repository:
用于标注数据访问组件,即DAO组件;
2.4 @RequestMapping
注解提供路由信息。它告诉Spring任何来自"/"路径的HTTP请求都应该被映射到home方法。@RestController注解告诉Spring以字符串的形式渲染结果,并直接返回给调用者。该注解有六个属性:
(1)params:指定request中必须包含某些参数值是,才让该方法处理。
(2)headers:指定request中必须包含某些指定的header值,才能让该方法处理请求。
(3)value:指定请求的实际地址,指定的地址可以是URI Template 模式
(4)method:指定请求的method类型, GET、POST、PUT、DELETE等
(5)consumes:指定处理请求的提交内容类型(Content-Type),如application/json,text/html
(6)produces:指定返回的内容类型,仅当request请求头中的(Accept)类型中包含该指定类型才返回
2.5 @Qualifier:
当有多个同一类型的Bean时,可以用@Qualifier(“name”)来指定。与@Autowired配合使用;
2.6 @EnableAutoConfiguration
第二个类级别的注解是@EnableAutoConfiguration。这个注解告诉Spring Boot根据添加的jar依赖猜测你想如何配置Spring。由于spring-boot-starter-web添加了Tomcat和Spring MVC,所以auto-configuration将假定正在开发一个web应用并相应地对Spring进行设置。Starter POMs和Auto-Configuration设计auto-configuration的目的是更好的使用"Starter POMs",但这两个概念没有直接的联系。可以自由地挑选starter POMs以外的jar依赖,并且Spring Boot将仍旧尽最大努力去自动配置你的应用。
你可以通过将@EnableAutoConfiguration或@SpringBootApplication注解添加到一个@Configuration类上来选择自动配置。
2.7 @Configuration
@Configuration注解该类,等价与XML中配置beans;用@Bean标注方法等价于XML中配置bean。
2.8 @Profiles
Spring Profiles提供了一种隔离应用程序配置的方式,并让这些配置只能在特定的环境下生效。任何@Component或@Configuration都能被@Profile标记,从而限制加载它的时机。
2.9 @全局异常处理
@ControllerAdvice:包含@Component。可以被扫描到。统一处理异常。
@ExceptionHandler(Exception.class):用在方法上面表示遇到这个异常就执行以下方法
2.10 @JsonBackReference
解决嵌套外链问题
2.11 @Conditional
通过@Conditional注解可以根据代码中设置的条件装载不同的bean,在设置条件注解之前,先要把装载的bean类去实现Condition接口,然后对该实现接口的类设置是否装载的条件
三、Springboot2.0新特性
3.1 基于Java 8,支持 Java 9
也就是说Spring Boot2.0的最低版本要求为JDK8,据了解国内大部分的互联网公司系统都还跑在JDK1.6/7上,因此想要升级到Spring Boot2.0的同学们注意啦,同时支持了Java9,也仅仅是支持而已。
3.2 响应式编程
使用Spring WebFlux/WebFlux.fn提供响应式 Web 编程支持, Webflux 是一个全新的非堵塞的函数式 Reactive Web 框架,可以用来构建异步的、非堵塞的、事件驱动的服务,在伸缩性方面表现非常好,此功能来源于Spring5.0。
Spring Boot2.0也提供对响应式编程的自动化配置,如:Reactive Spring Data、Reactive Spring Security 等
3.3 HTTP/2支持
在Tomcat, Undertow和 Jetty 中均已支持 HTTP/2
3.4 对Kotlin支持
引入对Kotlin 1.2.x的支持,并提供了一个 runApplication 函数,让你通过惯用的 Kotlin 来运行 Spring Boot 应用程序。
3.5 支持Quartz
Spring Boot1.0并没有提供对 Quartz 的支持,之前出现了各种集成方案,Spring Boot2.0给出了最简单的集成方式。
3.6 Security
大大的简化了安全自动配置
3.7 Metrics
Metrics方面,Spring Boot 2引入了Micrometer,来统一metrics的规范,使得开发人员更好的理解和使用metrics的模块,而不需要关心对接的具体存储是什么。
3.8 监控方面
Spring Boot 2增强了对 Micrometer 的集成。RabbitMQ、JVM 线程和垃圾收集指标会自动进行 instrument 监控,异步控制器(controller)也会自动添加到监控里。通过集成,还可以对 InfluxDB 服务器进行监控。
3.9 数据方面
db方面,默认引入了HikariCP,替代了之前的tomcat-pool作为底层的数据库连接池, 对比于tomcat-pool, HikariCP拥有更好的性能,总而言之就是提高了db的访问速度
JOOQ的支持
3.10 Redis方面
默认引入了Lettuce,替代了之前的jedis作为底层的redis链接方式
MongoDB\Hibernate优化
3.11 Thymeleaf 3
Spring Boot 2支持了Thymeleaf 3,Thymeleaf 3相对于Thymeleaf 2性能提升可不是一点点,因为2.0的性能确实不咋地,同时也使用了新的页面解析系统。
3.12 OAuth 2.0
同时也加入了对于OAuth 2.0的支持, 使得开发人员更加友好的使用spring-security来完成权限模块的开发
四、Springboot的实现原理
4.1 Conditional注解
背后全依赖于@Conditional注解来实现的,用于根据特定条件来控制Bean的创建行为。
@SpringBootApplication = (默认属性)@Configuration + @EnableAutoConfiguration + @ComponentScan。
4.2深入探索SpringApplication执行流程
SpringApplication的run方法的实现是我们本次旅程的主要线路,该方法的主要流程大体可以归纳如下:
1) 如果我们使用的是SpringApplication的静态run方法,那么,这个方法里面首先要创建一个SpringApplication对象实例,然后调用这个创建好的SpringApplication的实例方法。在SpringApplication实例初始化的时候,它会提前做几件事情:
A.根据classpath里面是否存在某个特征类(org.springframework.web.context.ConfigurableWebApplicationContext)来决定是否应该创建一个为Web应用使用的ApplicationContext类型。
B.使用SpringFactoriesLoader在应用的classpath中查找并加载所有可用的ApplicationContextInitializer。
C.使用SpringFactoriesLoader在应用的classpath中查找并加载所有可用的ApplicationListener。
D.推断并设置main方法的定义类。
2) SpringApplication实例初始化完成并且完成设置后,就开始执行run方法的逻辑了,方法执行伊始,首先遍历执行所有通过SpringFactoriesLoader可以查找到并加载的SpringApplicationRunListener。调用它们的started()方法,告诉这些SpringApplicationRunListener,“嘿,SpringBoot应用要开始执行咯!”。
3) 创建并配置当前Spring Boot应用将要使用的Environment(包括配置要使用的PropertySource以及Profile)。
4) 遍历调用所有SpringApplicationRunListener的environmentPrepared()的方法,告诉他们:“当前SpringBoot应用使用的Environment准备好了咯!”。
5) 如果SpringApplication的showBanner属性被设置为true,则打印banner。
6) 根据用户是否明确设置了applicationContextClass类型以及初始化阶段的推断结果,决定该为当前SpringBoot应用创建什么类型的ApplicationContext并创建完成,然后根据条件决定是否添加ShutdownHook,决定是否使用自定义的BeanNameGenerator,决定是否使用自定义的ResourceLoader,当然,最重要的,将之前准备好的Environment设置给创建好的ApplicationContext使用。
7) ApplicationContext创建好之后,SpringApplication会再次借助Spring-FactoriesLoader,查找并加载classpath中所有可用的ApplicationContext-Initializer,然后遍历调用这些ApplicationContextInitializer的initialize(applicationContext)方法来对已经创建好的ApplicationContext进行进一步的处理。
8) 遍历调用所有SpringApplicationRunListener的contextPrepared()方法。
9) 最核心的一步,将之前通过@EnableAutoConfiguration获取的所有配置以及其他形式的IoC容器配置加载到已经准备完毕的ApplicationContext。
10) 遍历调用所有SpringApplicationRunListener的contextLoaded()方法。
11) 调用ApplicationContext的refresh()方法,完成IoC容器可用的最后一道工序。
12) 查找当前ApplicationContext中是否注册有CommandLineRunner,如果有,则遍历执行它们。
13) 正常情况下,遍历执行SpringApplicationRunListener的finished()方法、(如果整个过程出现异常,则依然调用所有SpringApplicationRunListener的finished()方法,只不过这种情况下会将异常信息一并传入处理)
去除事件通知点后,整个流程如下:
4.3 Springboot实现总览:
上图为SpringBoot启动结构图,我们发现启动流程主要分为三个部分,第一部分进行SpringApplication的初始化模块,配置一些基本的环境变量、资源、构造器、监听器,第二部分实现了应用具体的启动方案,包括启动流程的监听模块、加载配置环境模块、及核心的创建上下文环境模块,第三部分是自动化配置模块,该模块作为springboot自动配置核心,在后面的分析中会详细讨论。在下面的启动程序中我们会串联起结构中的主要功能。
启动:
每个SpringBoot程序都有一个主入口,也就是main方法,main里面调用SpringApplication.run()启动整个spring-boot程序,该方法所在类需要使用@SpringBootApplication注解,以及@ImportResource注解(if need),@SpringBootApplication包括三个注解,功能如下:
@EnableAutoConfiguration:SpringBoot根据应用所声明的依赖来对Spring框架进行自动配置。
@SpringBootConfiguration(内部为@Configuration):被标注的类等于在spring的XML配置文件中(applicationContext.xml),装配所有bean事务,提供了一个spring的上下文环境。
@ComponentScan:组件扫描,可自动发现和装配Bean,默认扫描SpringApplication的run方法里的Booter.class所在的包路径下文件,所以最好将该启动类放到根包路径下。
4.4 SpringApplication的run()方法探秘
先看看代码长啥样子:
各个主要步骤我已经标注在上图之中了,除此之外,我也按照自己的理解画了一个流程图如下所示,可以对照数字标示看一下: