- Spring Boot 是如何简化Java 开发的
- SpringBoot的一些重要特征
长久以来,Spring 框架作为Java应用开发的框架地位稳固。最近在云计算、大数据、无结构数据持续化、函数式反应型编程和C端应用开发等方面,Spring生态内部成果不断,比较火爆的当属pring Boot。Spring Boot 提供了一种最小化配置的Java应用开发模式。Spring Boot大大简化了应用的配置,让程序员更加敏捷的开发,将更多的精力放在业务处理上。
Spring是通过依赖注入和面向切面编程,给POJO赋予了EJB的能力,替代了笨重的J2EE,成为轻量级的企业级Java应用开发框架。但是Spring的轻量级指的是POJO的轻量级,在配置方面还是很重。Spring 2.5 时代使用笨拙的XML文件作为配置,后来引入了Annotation(注解),情况开始改观。Spring 3.0 引入了基于Java的配置,作为一种类型安全、可重构的XML的替代配置方式,进步不小。但是,用Spring繁重的配置还是跑不了的。比如使用事务管理、Spring-MVC 还是需要特定的配置;使用第三方的模板渲染要引入特定的包;定制Servlet和Filter需要配置web.xml文件;凡此种种。Spring归根结底还是需要各种配置。。。
想想看,写代码的时候想着这个东西要用起来要先配置,业务逻辑写到一半,搞半天配置回来接着干;然后又遇到和什么东西还要再去配置一把。码农写东西还是比较忌讳来回这种切换的,而且配置很多都是体力活儿,配置写错了,调试的时候也是个坑。还有就是pom管理,每引入一个新的包都胆战心惊,冲突了要解决,一次解决不完还要来第二次,第三次。。。要是个老掉牙的工程,高冲突都能得搞到抑郁症。这些都是生产力杀手。
Spring Boot 来了,某种程度上,码农得救了。
俯瞰Spring Boot
假设现在写一个Web版本的Hello World。最少也要做下面几件事(也可以Google一下具体的创建过程)
- 用Maven(或者Gradle)创建一个工程架子,当然了Web应用的话,Spring MVC Servlet API的依赖肯定要在POM文件里面写好。
- 配置下web.xml(或者 WebApplicationInitializer 的 Implementation),声明Spring 的DispatcherServlet。
- 配置Spring,启用Spring MVC。
- 写一个处理Http请求的Controller。
- 准备一个Tomcat(或者WebLogic等)来承载当前的服务。
上面这些步骤,除了Controller的编写,其他的都和具体的业务没有直接关系。既然其他的步骤都是统一的,为什么不让工具或者框架帮助程序员做了呢?Spring Boot 某种意义上是可以做到的。举个例子(来自 Spring Boot In Action):写一个 HelloWorld 的Controller,使用Spring Boot的 CLI(Commond Line Interface)运行一下就可以了。
@RestController
class HelloController{
@RequestMapping("/")
def hello() {
return "Hello World".
}
}
Controller 写好后 用下面的命令执行一下就OK了。(具体的安装、使用CLI 后续慢慢写,现在就是知道下用Spring Boot开发,只要写好Controller,就可以运行的,编译都内置了)
$spring run HelloWorldController.groovy
剖析Spring Boot
Spring Boot 简化Java应用开发的手段有很多,核心内容有四个方面:
- 自动配置 -- Spring Boot 可以自动将应用中经常用到的、必要的配置完成。
- 完备的 starter 依赖 -- 程序员将应用中所需的功能告诉Spring Boot,Spring Boot 就可以将这个功能所需的依赖自动加进来。
- 命令行的运行 -- 这个可选的特性允许你只实现业务逻辑,就可以将整个应用运行起来,基本的工程框架都不需要(当然一般情况下,工程框架还是要有的)。
- 执行器 -- Actuator 提供整个应用的具体运行细节。
四个特点都通过各自的途径简化应用的开发。
AUTO-CONFIGURATION
在任意一个Java应用中,都可以找到一些XML形式或者Java形式的配置,这些配置负责启用某些功能或者提供某种特性。比如一个使用了JDBC进行数据库操作的应用,配置JdbcTemplate的形式看起来都差不多,类似下面的形式:
@Bean
public JdbcTemplate jdbcTemplate(DataSource dataSource) {
return new JdbcTemplate(dataSource);
}
当然这个时候一个 DataSource的实例需要注入到JdbcTemplate 中,假设DataSource 选用Spring内置的H2的数据库,那么DataSource 的代码差不多是下面这样的:
@Bean
public DataSource dataSource() {
return new EmbeddedDataSourceBuilder()
.setType(EmbeddedDatabaseType.H2)
.addScripts('schema.sql','data.sql')
.build();
}
上面这些代码就是Spring 冗余配置的典型代表。数据库的CURD在几乎所有的应用里都会用的到,简而言之这些代码都是套路,既然是套路当然可以交给Spring Boot 来做,这些套路包括但不限于 JPA、安全、SpringMVC 等等。具体的用法后续慢慢写。
STARTER DEPENDENCY
为工程添加依赖是个很有挑战的任务,具体需要哪些包?这些包的groupId 和 artifactId 是什么?选啥版本好呢?这个版本的包或者这个包本身与工程内部已有的包能不能和平共处不冲突呢?这些都不好说。。Spring Boot 通过 starter 依赖在一定程度上解决了这些问题。starter的本质是利用Maven或者Gradle 的传递依赖特性,通过一系列的 starter 的依赖将常用的包引入到工程中,并且保证通过starter引入的包能够保证相互之间是可以很好的工作的。举个例子,SpringMVC需要的包很多,spring-core/spring-web/spring-webmvc/tomcat/jsckson-databind/hibernate-validator等等。如果用starter依赖的话,org.springframework .boot:spring-boot-starter-web 这一个依赖就好了。
当让starter提供不仅限于传递依赖。其实引入了 web starter 也就说这个应用是个web应用,想要使用jpa就引入jpa starter,想要安全的包就引入 security starter 等等。这个时候要考虑的是这个工程需要什么,不需要再想具体需要哪些具体的包了。
THE COMMOND-LINE INTERFACE
除了以上两点外,Spring Boot 还提供了一种快速实现Spring 应用的方式 Spring Boot CLI。SpringBoot CLI 将自动化配置、starter 依赖的事情都承担起来,程序员只要关注业务逻辑实现就好了。$spring run HelloWorldController.groovy 看下这个命令和上面 Hello World 的Controller的代码,你会发现没有 import 各种包。那么CLI是怎么知道 RequestMapping 和 RestController 来自什么哪些 package?这些类是怎么被加载到classpath的呢?简单来说:Spring Boot 检测到这些类被用到了,这个时候Spring Boot 根据检测到的类就可以知道哪些哪些Starter 依赖需要被加载,Starter 依赖被加载后,传递依赖的包也会被加载到classpath;一系列的自动配置会被触发,DispatcherServlet Sping MVC 等等也会确保Controller可以响应Controller的HTTP的请求了。
当然SpringBoot的 CLI 是一个可选的特性,如果不能很适应这种比较极端的编程方式,当然可以可以选择比较传统的开发方式。不用Spring Boot的CLI不会影响对 Spring Boot 其他特性的使用。
THE ACTUATOR
上述特性提供了简化开发的方法,Actuator提供的特性是 让开发者可以清晰观察应用运行时的运行细节。 ACTUATOR 提供两种获取应用运行细节的方式:Web 形式 命令行方式。可以看到的信息大概包括一下几个方面:
- Spring Application Context 中被配置的Bean。
- Spring Boot 自动配置做了哪些决策。
- 应用中启用的环境变量、系统参数、配置属性、可用的命令行命令。
- 应用中线程的运行状态。
- 提供可视化的内存利用率、垃圾回收、Web 请求、数据源等信息。
关于 Spring Boot 一些说明
(a) Sping Boot 不是应用服务器。Spring Boot 通过一系列的内置的Tomcat 、DataSource、等等来完成应用的启动和部署。是tomcat / Jetty /Weblogic 来提供服务的,并不是Spring Boot 自身。(b) Spring Boot 并没有实现任何的企业级标准。之所以支持JPA或者JMS是因为Spring Boot 在Spring 中间相关的Bean进行了自动配置。(c)Spring Boot 并没有通过生成代码来完成一些特定功能。Spring 做的利用了Spring 4 中提供的 条件化配置 (Conditional Configuration)、Maven (Gradle)的传递依赖特性来实现自身的特性。Spring Boot 做了原本Spring不会帮开发者做的一些标准化、比较无趣的、不和逻辑实现强相关的工作。尽可能将开发者从非业务逻辑工作中解脱出来。