一、Spring Boot简介
Spring Boot makes it easy to create stand-alone, production-grade Spring based Applications that you can "just run".
We take an opinionated view of the Spring platform and third-party libraries so you can get started with minimum fuss. Most Spring Boot applications need minimal Spring configuration.
Spring Boot用来简化Spring应用开发,约定大于配置, 去繁从简,just run就能创建一个独立的,产品级别的应用。简言之,Spring Boot就是Spring,它只是做了一些没有它你自己也会做的事情,比如bean配置、版本依赖。

Spring Boot的主要特性如下:
Features
- Create stand-alone Spring applications
- Embed Tomcat, Jetty or Undertow directly (no need to deploy WAR files)
- Provide opinionated 'starter' dependencies to simplify your build configuration
- Automatically configure Spring and 3rd party libraries whenever possible
- Provide production-ready features such as metrics, health checks, and externalized configuration
- Absolutely no code generation and no requirement for XML configuration
每一个特性都在通过自己的方式简化Spring应用程序的开发。 我们今天的重点是自动配置,也会附带说一些起步依赖相关的东西。
二、Hello World 入门
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>spring-boot-01-helloworld</artifactId>
<version>1.0-SNAPSHOT</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.9.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
</project>
@RestController
public class HelloController {
@RequestMapping("/hello")
String hello() {
return "你好,World!";
}
}
// @SpringBootApplication 来标注一个主程序类,说明这是一个Spring Boot应用
@SpringBootApplication
public class HelloWorldMainApplication {
public static void main(String[] args) throws Exception {
// Spring应用启动起来
SpringApplication.run(HelloWorldMainApplication.class, args);
}
}
运行main方法后,浏览器中输入http://localhost:8080/hello,显示如下:

小结如下:
(1)从父项目spring-boot-starter-parent继承了通用的依赖
(2)spring-boot-starter-web帮我们导入了web模块正常运行所依赖的组件
(3)运行main方法后,加载主程序类所在的包及子包的组件,并开启自动配置,将大量的自动配置组件添加到容器中。
三、起步依赖
如果没有起步依赖,对于上面的HelloWord入门web程序的依赖引入,你会考虑哪些呢?
- 引入哪些依赖
- 引入依赖的版本
- 依赖之间是否可以兼容
- ......
来看看spring boot如何通过提供众多起步依赖降低项目依赖的复杂度?
起步依赖本质上是一个Maven项对象模型(Project Object Model,POM),定义了对其他库的传递依赖,加在一起即支持某项功能。如果你需要一个web应用程序,则添加spring-boot-starter-web起步依赖,如果你需要能在Spring Boot上下文里运行集成测试的库,则添加spring-boot-starter-test起步依赖。
Spring Boot将所有的功能场景都抽取出来,对应不同的起步依赖。要用什么功能,只需要在项目里面引入这些功能对应的起步依赖,相关的依赖都会导入进来。Spring Boot经过了足够的测试,确保引入的全部依赖都能相互兼容。
起步依赖的命名都暗示了它们提供的某种或某类功能,可以参考https://docs.spring.io/spring-boot/docs/1.5.9.RELEASE/reference/htmlsingle/#using-boot-starter
四、自动配置原理
Spring Boot启动的时候加载主程序类,开启自动配置功能。在这里将注解发挥到了极致,了解了自动配置功能涉及的核心注解,也就知道了spring boot是如何进行自动配置的。

3.1 SpringBootApplication
@SpringBootConfiguration标注在某个类上,表示这是一个Spring Boot的配置类。这个注解等价于Configuration+EnableAutoConfiguration+ComponentScan
3.2 EnableAutoConfiguration
自动配置的核心注解,核心见3.3和3.4
3.3 AutoConfigurationPackage
将AutoConfigurationPackages.Registrar.class对应的实例添加到容器中,该实例会存储用户自定义的自动配置包列表。 从截图中可以看出,主程序类所在的包会作为自动配置包存储下来。

Spring Boot其它地方可以通过静态方法AutoConfigurationPackages.get获取这个自动配置包列表,从而进行自动扫描,如:
protected String[] getPackagesToScan() {
List<String> packages = EntityScanPackages.get(this.beanFactory).getPackageNames();
if (packages.isEmpty() && AutoConfigurationPackages.has(this.beanFactory)) {
packages = AutoConfigurationPackages.get(this.beanFactory);
}
return packages.toArray(new String[packages.size()]);
}
3.4 Import(EnableAutoConfigurationImportSelector.class)
导入组件的选择器,Spring Boot在启动的时候从EnableAutoConfiguration类路径下的META-INF/spring.factories中获取EnableAutoConfiguration指定的值,这些值对应的组件经过筛选后就会被添加到容器中


3.5 @Conditional扩展注解
自动配置类必须在一定的条件下才能生效,通过@Conditional及扩展注解,不同的自动配置组件可以灵活地配置生效条件,比如下面这个自动配置组件在以下两个条件均满足时才会被加载到容器中:
- 当前是web环境
- 类路径下存在DispatcherServlet.class
@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE)
@Configuration
@ConditionalOnWebApplication
@ConditionalOnClass(DispatcherServlet.class)
@AutoConfigureAfter(EmbeddedServletContainerAutoConfiguration.class)
public class DispatcherServletAutoConfiguration {
......
}
@Conditional常见扩展注解列举如下:
@Conditional扩展注解 | 作用(判断是否满足当前指定条件) |
---|---|
@ConditionalOnJava | 系统的java版本是否符合要求 |
@ConditionalOnBean | 容器中存在指定Bean; |
@ConditionalOnMissingBean | 容器中不存在指定Bean; |
@ConditionalOnExpression | 满足SpEL表达式指定 |
@ConditionalOnClass | 系统中有指定的类 |
@ConditionalOnMissingClass | 系统中没有指定的类 |
@ConditionalOnSingleCandidate | 容器中只有一个指定的Bean,或者这个Bean是首选Bean |
@ConditionalOnProperty | 系统中指定的属性是否有指定的值 |
@ConditionalOnResource | 类路径下是否存在指定资源文件 |
@ConditionalOnWebApplication | 当前是web环境 |
@ConditionalOnNotWebApplication | 当前不是web环境 |
@ConditionalOnJndi | JNDI存在指定项 |
我们可以通过启用debug=true属性,来让控制台打印自动配置报告,这样我们就可以更方便地知道哪些自动配置类被加载到了容器中。

五、自定义配置
spring boot在装配自动配置组件时,使用默认的配置,可以通过编写配置文件来替换这些默认的配置。如何知道配置文件中可以编写哪些配置呢?接下来以自动配置组件HttpEncodingAutoConfiguration为例进行介绍。

HttpEncodingProperties类上注解EnableConfigurationProperties的作用是支持从配置文件中获取指定的值和bean的属性进行绑定,HttpEncodingProperties类中定义了哪些属性,我们就可以在自己定义的配置文件中重新配置哪些属性。


charset默认的编码格式为UTF-8,尝试设置为ISO-8859-1后,中文会出现乱码


网友评论