中台指南系列一:SpringBoot开发指南

目前部门正在向平台化和中台化方面转变,基于这个背景,我对中台的一些理论进行了一些探索。可以说,未来任何一项技术的研发不能是孤立的,必须自上而下有一个体系化的思考和解决方案。今天做中台和平台不是为了明天变得更少,而是为了明天变得更大更快更颠覆。希望我整理的文档和研发的技术能帮到大家。
更多详情请点击:中台技术体系建设的探索之路

1 前言

SpringBoot微框架目前已经风靡了整个阿里技术社区,主要有AE-SpringBoot和PandoraBoot两个团队在这方面深耕细作,致力于为大家提供一些公共的Starter和问题答疑。我为了迎合团队基础技术建设的趋势,也着手用Starter开了一些基础组件和业务组件,写本文的目的是想把开发中积累的一些经验总结一下,期望能帮助到那些想了解Starter并进行开发的同学。
在本文开始前,我们先要了解下SpringBoot是什么,可以说SpringBoot框架的命名关键在“Boot”上,也就是快速启动一个Spring应用。从最根本上来讲,Spring Boot就是一些库的集合,它能够被任意项目的构建系统所使用。SpringBoot的优势如下:
1)Spring Boot使编码变简单,使用Starter POM管理包依赖,天然地集成了一些开发框架等;
2)Spring Boot使配置变简单,采用Java Config减少了繁琐的配置;
3)Spring Boot使部署变简单,跟Docker结合部署内嵌的容器;
4)Spring Boot使监控变简单,Actuator和Health Check提供了完善的监控方案。

2 SpringBoot核心知识

2.1 SpringApplication

SpringApplication将一个典型的Spring应用启动流程“模板化”,并在合适的流程结点开放了一系列不同类型的扩展点,让我们根据需求自由进行扩展。SpringBoot的一站式启动流程如下:
1、如果我们使用的是SpringApplication的静态run方法,那么,这个方法里面首先要创建一个SpringApplication对象实例,然后调用这个创建好的SpringApplication的实例方法。在SpringApplication实例初始化的时候,它会提前做几件事情:
1)根据classpath里面是否存在某个特征类ConfigurableWebApplicationContext来决定是否应该创建一个为Web应用使用的ApplicationContext类型。
2)使用SpringFactoriesLoader在应用的classpath中查找并加载所有可用的ApplicationContextInitializer。
3)使用SpringFactoriesLoader在应用的classpath中查找并加载所有可用的ApplicationListener。
4)推断并设置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()方法,只不过这种情况下会将异常信息一并传入处理)。
整个过程看起来冗长无比,但其实很多都是一些事件通知的扩展点,如果我们将这些逻辑暂时忽略,那么,其实整个SpringBoot应用启动的逻辑就可以压缩到极其精简的几步:
springboot - 图1

2.2 静态资源

在web开发中,静态资源的访问是必不可少的,例如图片、js、css等资源的访问。SpringBoot对静态资源访问提供了很好的支持,基本使用默认配置就能满足开发需求。
一、默认静态资源映射
SpringBoot默认将 “/**” 所有访问映射到以下目录,优先级从高到底:

  1. classpath:/META-INF/resources
  2. classpath:/resources
  3. classpath:/static
  4. classpath:/public

二、自定义静态资源映射
在实际开发中,可能需要自定义静态资源访问路径,那么可以继承WebMvcConfigurerAdapter来实现。
1、静态资源配置类

@Configuration
public class WebMvcConfig extends WebMvcConfigurerAdapter {
    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        //将所有/static/** 访问都映射到classpath:/static/ 目录下
        registry.addResourceHandler("/static/**").addResourceLocations("classpath:/static/");
    }
}

2、在application.properties配置

spring.mvc.static-path-pattern=/static/**

2.3 日志配置

SpringBoot在所有内部日志中使用Commons Logging,但是默认配置也提供了对常用日志的支持,如:Java Util Logging,Log4J, Log4J2和Logback。Spring Boot默认使用Logback来记录日志。
1、自定义日志文件配置
由于日志服务一般都在ApplicationContext创建前就初始化了,它并不是必须通过Spring的配置文件控制。因此通过系统属性和传统的Spring Boot外部配置文件依然可以很好的支持日志控制和管理。根据不同的日志系统,你可以按如下规则组织配置文件名,就能被正确加载:
1)Logback:logback-spring.xml, logback-spring.groovy, logback.xml, logback.groovy
2)Log4j:log4j-spring.properties, log4j-spring.xml, log4j.properties, log4j.xml
3)Log4j2:log4j2-spring.xml, log4j2.xml
4)JDK (Java Util Logging):logging.properties
SpringBoot官方推荐优先使用带有-spring的文件名作为你的日志配置,SpringBoot可以为它添加一些SpringBoot特有的配置项。
2、日志参数配置

logging:
    file:   # 日志文件,绝对路径或相对路径
    path:   # 保存日志文件目录路径
    config: # 日志配置文件,Spring Boot默认使用classpath路径下的日志配置文件
    level:  # 日志级别
        org.springframework.web: DEBUG # 配置spring web日志级别

这些属性配置在不同地方的优先级:Diamond > application.properties > logback-spring.xml
3、日志级别控制
配置格式:logging.level. = LEVEL
logging.level:日志级别控制前缀,
为包名或Logger名
LEVEL:选项TRACE, DEBUG, INFO, WARN, ERROR, FATAL, OFF
配置举例:

logging.level.com.union.demo=DEBUG:com.union.demo包下所有class以DEBUG级别输出
logging.level.root=WARN:root日志以WARN级别输出

自SpringBoot 1.5版本,我们可以通过端点/loggers查看所有日志的配置,也可以通过/loggers/查看具体包名或者Logger名的日志级别,通过发送Post请求也可以动态修改日志级别。
*4、控制台输出

在Spring Boot中默认配置了ERROR、WARN和INFO级别的日志输出到控制台。我们可以通过两种方式切换至DEBUG级别:
1)在运行命令后加入—debug标志,如:$ java -jar myapp.jar —debug。
2)在application.properties中配置debug=true,该属性置为true的时候,核心Logger(包含嵌入式容器、hibernate、spring)会输出更多内容,但是你自己应用的日志并不会输出为DEBUG级别。
如果你的终端支持ANSI,设置彩色输出会让日志更具可读性。通过在application.properties中设置spring.output.ansi.enabled参数来支持。
1)NEVER:禁用ANSI-colored输出(默认项)。
2)DETECT:会检查终端是否支持ANSI,是的话就采用彩色输出(推荐项)。
3)ALWAYS:总是使用ANSI-colored格式输出,若终端不支持的时候,会有很多干扰信息,不推荐使用。

2.4 Actuator监控

spring-boot-actuator模块提供了一个监控和管理生产环境的模块,可以使用http、jmx、ssh、telnet等拉管理和监控应用。审计(Auditing)、健康(health)、数据采集(metrics gathering)会自动加入到应用里面。
一、原生监控端点分类
1)应用配置类:获取应用程序中加载的应用配置、环境变量、自动化配置报告等与Spring Boot应用密切相关的配置类信息。
2)度量指标类:获取应用程序运行过程中用于监控的度量指标,比如:内存信息、线程池信息、HTTP请求统计等。
3)操作控制类:提供了对应用的关闭等操作类功能。
一、监控端点暴露功能

HTTP方法 路径 描述 鉴权
GET /autoconfig 查看自动配置的使用情况 true
GET /configprops 查看配置属性,包括默认配置 true
GET /beans 查看bean及其关系列表 true
GET /dump 打印线程栈 true
GET /env 查看所有环境变量 true
GET /env/{name} 查看具体变量值 true
GET /health 查看应用健康指标 false
GET /info 查看应用信息 false
GET /mappings 查看所有url映射 true
GET /metrics 查看应用基本指标 true
GET /metrics/{name} 查看具体指标 true
POST /shutdown 关闭应用 true
GET /trace 查看基本追踪信息 true
GET/POST /loggers 动态修改日志级别 true

更多信息请看:监控端点小结

2.5 Profile多环境配置

什么是Profile呢?很多时候,我们项目在开发环境和生成环境的环境配置是不一样的,例如,数据库配置,在开发的时候,我们一般用测试数据库,而在生产环境的时候,我们是用正式的数据,这时候,我们可以利用profile在不同的环境下用不同的配置文件。
可以用spring.profiles.active来激活一个或者多个profile:

spring.profiles.active=env

1)各个环境公共的配置写在application.properties中。
2)各个模块独有的配置配置在自己的application-{env}.properties文件中。
3)程序先读取spring.profiles.active中设置的profile配置,读不到才会application.properties去取。
还可以用spring.profiles.include来叠加profile:

spring.profiles: env1
spring.profiles.include: env2,env3

3 SpringBoot注解知识

3.1 SpringBootApplication注解

@SpringBootApplication是一个“三体”结构,实际上是一个复合Annotation:

@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan

要想理解@SpringBootApplication这个注解,就必须对它构成的注解进行分析:
一、@Configuration
@SpringBootConfiguration包含@Configuration,而@Configuration是用注解配置Spring,也就是说这是个配置文件,和原来xml配置是等效的,只不过现在用java代码进行配置了并加上一个@Configuration注解就行了。很多SpringBoot的代码示例都喜欢在启动类上直接标注@Configuration或者@SpringBootApplication,对于初学者不便于理解,如果拆分为两个独立的Java类,那么就更清晰了:

@Configuration
@EnableAutoConfiguration
@ComponentScan
public class DemoConfiguration {
    @Bean
    public Controller controller() {
        return new Controller();
    }
}
public class DemoApplication {
    public static void main(String[] args) {
        SpringApplication.run(DemoConfiguration.class, args);
    }
}

所以,启动类DemoApplication其实就是一个标准的Standalone类型Java程序的main函数启动类,没有什么特殊的。而@Configuration标注的DemoConfiguration定义其实也是一个普通的JavaConfig形式的IoC容器配置类。
二、@EnableAutoConfiguration
@EnableAutoConfiguration其实也是一个复合Annotation:

@AutoConfigurationPackage
@Import(EnableAutoConfigurationImportSelector.class)

其中@Import(EnableAutoConfigurationImportSelector.class)最为关键,借助EnableAutoConfigurationImportSelector,@EnableAutoConfiguration可以帮助SpringBoot应用将所有符合条件的@Configuration配置都加载到当前SpringBoot创建并使用的IoC容器,就像“八爪鱼”一样:
springboot - 图2
借助于Spring框架原有的一个工具类SpringFactoriesLoader的支持,@EnableAutoConfiguration的“智能”自动配置功效才能够发挥作用。SpringFactoriesLoader主要功能就是从指定的配置文件META-INF/spring.factories加载配置,spring.factories配置的格式为Key=Value形式,比如:

example.MyService=example.MyServiceImpl1,example.MyServiceImpl2

然后框架就可以根据某个类型作为Key来查找对应的类型名称列表了,并将其中含有@EnableAutoConfiguration对应的配置项通过Java反射实例化为对应的标注了@Configuration的JavaConfig形式的IoC容器配置类,然后汇总为一个并加载到IoC容器。
三、@ComponentScan
@ComponentScan的功能其实就是自动扫描并加载符合条件的组件或bean定义,最终将这些bean定义加载到容器中。加载bean定义到Spring的IoC容器,我们可以手工单个注册,不一定非要通过批量的自动扫描完成,所以说@ComponentScan是可有可无的。
一般将SpringBoot启动类放在需要扫描的包的根路径下,就不需要额外配置@ComponentScan了。

3.2 Value注解

一、注入方式
1)注入普通字符串
2)注入操作系统属性
3)注入表达式结果
4)注入其他Bean属性:注入beanInject对象的属性another
5)注入文件资源
6)注入URL资源

@Value("normal")
private String normal; // 注入普通字符串
@Value("#{systemProperties['os.name']}")
private String systemPropertiesName; // 注入操作系统属性
@Value("#{ T(java.lang.Math).random() * 100.0 }")
private double randomNumber; //注入表达式结果
@Value("#{beanInject.another}")
private String fromAnotherBean; // 注入其他Bean属性:注入beanInject对象的属性another,类具体定义见下面
@Value("classpath:com/hry/spring/configinject/config.txt")
private Resource resourceFile; // 注入文件资源
@Value("http://www.baidu.com")
private Resource testUrl; // 注入URL资源

注入其他Bean属性:注入beanInject对象的属性another

@Component
public class BeanInject {
    @Value("其他Bean的属性")
    private String another;
    public String getAnother() {
        return another;
    }
    public void setAnother(String another) {
        this.another = another;
    }
}

一、使用方法
1、#{…}使用方法
通过@Value(“spelDefault.value”)可以获取属性文件中对应的值,但是如果属性文件中没有这个属性,则会报错。可以通过赋予默认值解决这个问题,如@Value(“spelDefault.value”)可以获取属性文件中对应的值,但是如果属性文件中没有这个属性,则会报错。可以通过赋予默认值解决这个问题,如@Value(“{spelDefault.value:127.0.0.1}”)

// 如果属性文件没有spelDefault.value,则会报错
//  @Value("${spelDefault.value}")
//  private String spelDefault2;
// 使用default.value设置值,如果不存在则使用默认值
@Value("${spelDefault.value:127.0.0.1}")
private String spelDefault;

2、${…}使用方法
${…}的{}里面的内容必须符合SpEL表达式,语法详情查看:SpEL表达式语法

// SpEL:调用字符串Hello World的concat方法
@Value("#{'Hello World'.concat('!')}")
private String helloWorld;
// SpEL: 调用字符串的getBytes方法,然后调用length属性
@Value("#{'Hello World'.bytes.length}")
private String helloWorldbytes;

3.3 Conditional注解

Conditional的官方文档定义为:“Indicates that a component is only eligible for registration when all specified conditions match”,意思是只有满足一些列条件之后创建一个bean。
1、注解定义

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.METHOD})
public @interface Conditional {
    Class<? extends Condition>[] value();
}

2、注解位置
1)类级别可以放在注标识有@Component(包含@Configuration)的类上。
2)作为一个meta-annotation组成自定义注解。
3)方法级别可以放在标识由@Bean的方法上。
3、常用注解

注解名称 注解作用
ConditionalOnMissingBean 判断是否执行初始化代码,即如果用户已经创建了bean,则相关的初始化代码不再执行
ConditionalOnBean 当且仅当指定的bean classes and/or bean names在当前容器中,才创建标记上该注解的类的实例
ConditionalOnBean 当且仅当指定的bean classes and/or bean names不存在当前容器中,才创建标记上该注解的类的实例,有指定忽略ignored的参数存在,可以忽略Class、Type等
ConditionalOnClass 当且仅当ClassPath存在指定的Class时,才创建标记上该注解的类的实例
ConditionalOnMissingClass 当且仅当ClassPath不存在指定的Class时,创建标记上该注解的类的实例
ConditionalOnProperty 当且仅当Application.properties存在指定的配置项时,创建标记上了该注解的类的实例
ConditionalOnExpression 表达式用${..}=false等来表示
ConditionalOnResource 在classpath下存在指定的resource时创建
ConditionalOnWebApplication 在web环境下创建

3.4 调整Bean顺序

我们可以使用@AutoConfigureBefore或者@AutoConfigureAfter让当前配置或者组件在某个其他组件之前或者之后进行,比如,假设我们希望某些JMX操作相关的bean定义在MBeanServer配置完成之后进行,那么我们就可以提供一个类似如下的配置:

@Configuration
@AutoConfigureAfter(JmxAutoConfiguration.class)
public class AfterMBeanServerReadyConfiguration {
    @Autowired
    MBeanServer mBeanServer;
    ......
}

4 SpringBoot属性知识

4.1 属性自动装配原理

一、Properties属性示例
1、定义Properties类

@ConfigurationProperties(prefix = "union.demo")
public class DemoProperties {
    private String name;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
}

2、添加配置

spring.demo.name=test

3、注入Properties类

@Configuration
@EnableConfigurationProperties({DemoProperties.class})
public class DemoConfiguration {
}

二、属性自动装配实现
1、在解析@Congiguration的时候,会调用@Import中引入的类;
1)如果@Import中是ImportBeanDefinitionegistar的子类,会直接调用registerBeanDefinitions;
2)如果@Import中是ImportSelector类型,会调用selectImports()返回的bean的registerBeanDefinitions方法;
前者是为了注入配置properties类,后者为属性绑定值。
2、registerBeanDefinitions方法会向BeanFactory中添加新的bean。
注意这里注入了ConfigurationPropertiesBindingPostProcessor,这才是属性赋值的关键:
springboot - 图3
注意到ConfigurationPropertiesBindingPostProcessor继承自BeanPostProcessor,他会在bean初始化前后调用before和after后置处理。
更详细的原理解释请看这里

4.2 属性配置优先级

SpringBoot的核心为“约定优先于配置”,优先级从高到底:
1)命令行参数
2)Diamond的Properties配置
3)Java系统属性(System Properties)
4)操作系统环境变量
5)jar包外部的application-{profile}.properties或application.yml(带spring.profile)配置文件
6)jar包内部的application-{profile}.properties或application.yml(带spring.profile)配置文件
7)jar包外部的application.properties或application.yml(不带spring.profile)配置文件
8)jar包内部的application.properties或application.yml(不带spring.profile)配置文件
9)@Configuration注解类上的@PropertySource
10)通过SpringApplication.setDefaultProperties指定的默认属性

4.3 属性配置格式

1、参数引用

com.sam.name=sam
com.sam.age=11
com.sam.desc=${name} is ${age} years old.

通过如${com.sam.name:默认名称}还可以设置默认值
2、获取随机数

#获取随机int:${random.int}
#获取10以内的随机数:${random.int(10)}
#获取10-20的随机数:${random.int[10,20]}
#获取随机long:${random.long}
#获取随机uuid:${random.uuid}
#获取随机字符串:${random.value}
com.sam.randomValue=${random.value}

3、支持yml语法

server:
  port: 9999

port: 9999 中间是有空格的,yml语法请参考:yml配置文件用法

4.4 属性读取方式

举个例子,我们在application.properties里添加一些属性信息:

union.demo.name=张三
union.demo.address[0]=北京
union.demo.address[1]=上海
union.demo.phone.number=1111111

对于属性的读取方式,我总结了有以下五种:
1、使用@Value

@Value("${union.demo.name}") 
private String name;

2、使用@ConfigurationProperties
1)首先定义Properties类

@Component
@ConfigurationProperties(prefix = "union.demo")
public class PeopleProperties {
    private String name;
    private List<String> address;
    private Phone phone;
    ......
}

2)然后注入Properties类

@Configuration
@EnableConfigurationProperties({PeopleProperties.class})
public class PeopleConfiguration {
    @Autowired(required = false)
    private PeopleProperties properties;
}

3、使用Environment
1)注入环境变量

@Autowired 
private Environment env;

2)使用环境变量进行访问:

env.getProperty("union.demo.name")

4、使用RelaxedDataBinder

PeopleProperties properties = new PeopleProperties();
MutablePropertySources propertySources = environment.getPropertySources();
new RelaxedDataBinder(properties, "union.demo").bind(
            new PropertySourcesPropertyValues(propertySources));

5、使用PropertiesLoaderUtils
通过注册监听器(Listeners) + PropertiesLoaderUtils的方式加载属性文件,比较复杂,这里不再赘述。

4.5 常用属性介绍

1、debugging
debug:会打印除应用之外其他的jar的日志。
spring.diamond.print-properties:设置为true时应用启动时,会打印出最终的Spring环境所有的key/value,还有从哪里加载的,方便调试。
2、mvc
spring.mvc.async.request-timeout:设定async请求的超时时间,以毫秒为单位,如果没有设置的话,以具体实现的超时时间为准,比如tomcat的servlet3的话是10秒。
spring.mvc.date-format:设定日期的格式,比如dd/MM/yyyy。
spring.mvc.favicon.enabled:是否支持favicon.ico,默认为: true。
spring.mvc.locale:指定使用的Locale。
spring.mvc.view.prefix:指定mvc视图的前缀。
spring.mvc.view.suffix:指定mvc视图的后缀。
3、resources
spring.resources.add-mappings:是否开启默认的资源处理,默认为true。
spring.resources.cache-period:设定资源的缓存时效,以秒为单位。
spring.resources.chain.cache:是否开启缓存,默认为:true。
spring.resources.chain.enabled:是否开启资源 handling chain,默认为false。
spring.resources.static-locations:指定静态资源路径。
4、multipart
multipart.enabled:是否开启文件上传支持,默认为true。
multipart.file-size-threshold:设定文件写入磁盘的阈值,单位为MB或KB,默认为0。
multipart.location:指定文件上传路径。
multipart.max-file-size:指定文件大小最大值,默认1MB。
multipart.max-request-size:指定每次请求的最大值,默认为10MB。
5、http
spring.http.converters.preferred-json-mapper:是否优先使用JSON mapper来转换.
spring.http.encoding.charset:指定http请求和相应的Charset,默认为UTF-8。
spring.http.encoding.enabled:是否开启http的编码支持,默认为true。
spring.http.encoding.force:是否强制对http请求和响应进行编码,默认为true。
6、json
spring.jackson.date-format:指定日期格式,比如yyyy-MM-dd HH:mm:ss。
spring.jackson.deserialization:是否开启Jackson的反序列化。
spring.jackson.generator:是否开启json的generators。
spring.jackson.joda-date-time-format:指定Joda date/time的格式,如果没有配置的话,dateformat会作为backup。
spring.jackson.locale:指定json使用的Locale。
spring.jackson.mapper:是否开启Jackson通用的特性。
spring.jackson.parser是否开启jackson的parser特性。
spring.jackson.serialization:是否开启jackson的序列化。
spring.jackson.time-zone:指定日期格式化时区,比如America/Los_Angeles或者GMT+10。
7、server
server.port:设定http监听端口。
server.address:指定server绑定的地址。
server.compression.enabled:是否开启压缩,默认为false。
server.compression.mime-types:指定要压缩的MIME type,多个以逗号分隔。
server.context-path:设定应用的context-path。
server.servlet-path:设定dispatcher servlet的监听路径,默认为“/”。
8、session
server.session.cookie.domain:指定session cookie的domain。
server.session.cookie.http-only:是否开启HttpOnly。
server.session.cookie.max-age:设定session cookie的最大age。
server.session.cookie.name:设定Session cookie 的名称。
server.session.cookie.path:设定session cookie的路径。
server.session.timeout:session的超时时间。
9、datasource
spring.datasource.initial-size:指定启动连接池时,初始建立的连接数量。
spring.datasource.connection-timeout:指定连接的超时时间,毫秒单位。
spring.datasource.max-active:指定连接池中最大的活跃连接数。
spring.datasource.max-age:指定连接池中连接的最大年龄。
spring.datasource.max-idle:指定连接池最大的空闲连接数量。
spring.datasource.max-lifetime:指定连接池中连接的最大生存时间,毫秒单位。
spring.datasource.max-wait:指定连接池等待连接返回的最大等待时间,毫秒单位。
spring.datasource.maximum-pool-size:指定连接池最大的连接数,包括使用中的和空闲的连接。
10、security
security.basic.authorize-mode:要使用权限控制模式。
security.basic.enabled:是否开启基本的鉴权,默认为true。
security.require-ssl:是否对所有请求开启SSL,默认为false。
security.sessions:指定Session的创建策略(always, never, if_required, stateless)。
security.user.name:指定默认的用户名,默认为user。
security.user.password:默认的用户密码。
security.user.role:默认用户的授权角色。
11、aop
spring.aop.auto:是否支持@EnableAspectJAutoProxy,默认为true。
spring.aop.proxy-target-class:true为使用CGLIB代理,false为JDK代理,默认为false。
更多SpringBoot属性请点我

5 Starter核心知识

5.1 Starter基本介绍

一、Starter的基本概念
可以认为Starter是一种服务,使得使用某个功能的开发者不需要关注各种依赖库的处理,不需要具体的配置信息,由SpringBoot自动通过classpath路径下的类发现需要的Bean,并织入bean。正规的starter是一个独立的工程,然后在maven中新仓库注册发布,其他开发人员就可以使用你的starter了。
二、starter的基本原理
虽然不同的starter实现起来各有差异,但是他们基本上都会使用到两个相同的内容:ConfigurationProperties和AutoConfiguration。因为Spring Boot坚信“约定大于配置”这一理念,所以我们使用ConfigurationProperties来保存我们的配置,并且这些配置都可以有一个默认值,即在我们没有主动覆写原始配置的情况下,默认值就会生效,这在很多情况下是非常有用的。除此之外,starter的ConfigurationProperties还使得所有的配置属性被聚集到一个文件中(一般在resources目录下的application.properties),这样我们就告别了Spring项目中XML地狱。
springboot - 图4
三、Starter包含内容
1、自动配置文件,根据classpath是否存在指定的类来决定是否要执行该功能的自动配置。
2、spring.factories,指导SpringBoot找到指定的自动配置文件。
3、endpoint:可以理解为一个admin,包含对服务的描述、界面、交互(业务信息的查询)
4、health indicator:该starter提供的服务的健康指标
四、Starter执行过程
在应用程序启动过程中,SpringBoot使用SpringFactoriesLoader查找EnableAutoConfiguration关键字对应的Java配置文件。Spring Boot会遍历在各个jar包种META-INF目录下的spring.factories文件,构建成一个配置文件链表。除了EnableAutoConfiguration关键字对应的配置文件,还有其他类型的配置文件:
org.springframework.context.ApplicationContextInitializer
org.springframework.context.ApplicationListener
org.springframework.boot.SpringApplicationRunListener
org.springframework.boot.env.PropertySourceLoader
org.springframework.boot.autoconfigure.template.TemplateAvailabilityProvider
org.springframework.test.contex.TestExecutionListener

5.2 Starter代码规范

1、Starter命名规范
命名规则:{Starter名称}-spring-boot-starter
规则描述:Starter名称如果由小写英文单词组成,名称前可以增加库名称。
规则举例:
tddl-spring-boot-starter
pandora-diamond-spring-boot-starter
union-core-spring-boot-starter
2、属性命名规范
命名规则:spring.{组件名称}.{属性名称}
规则描述:组件名称和属性名称都是由小写英文单词组成,多个英文单词用“-”分隔。
规则举例:
spring.doom.enabled
spring.diamond.data-id
spring.diamond.group-id

5.3 自定义Bom清单

SpringBoot通过maven的依赖管理为我们写好了很多依赖项及其版本,我们可直接拿来使用。主要有以下两种使用方法:
1、继承

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-parent</artifactId>
  <version>1.4.3.RELEASE</version>
  <type>pom</type>
</dependency>

2、导入

<dependencyManagement>
  <dependencies>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-dependencies</artifactId>
      <version>1.5.3.RELEASE</version>
      <type>pom</type>
      <scope>import</scope>
    </dependency>
    </dependencies>
</dependencyManagement>

此外,继承时可简单地通过属性定制依赖项版本。比如改为使用较新的spring版本:

<properties>
    <spring.version>4.1.6.RELEASE<spring.version>
</properties>

不过,此法只对继承有效,导入无效。那么导入时有没有较简单的方法呢?我们可先继承后导入。
1、先建一个过渡性工程,继承后定制依赖项的版本。

<project>
  <modelVersion>4.0.0</modelVersion>
  <parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-dependencies</artifactId>
    <version>1.5.3.RELEASE</version>
  </parent>
  <groupId>com.alibaba.union</groupId>
  <artifactId>union-boot-starter-bom</artifactId>
  <version>1.0.0-RELEASE</version>
  <packaging>pom</packaging>
  <properties>
    <spring.version>1.5.3.RELEASE</spring.version>
  </properties>
</project>

2、然后导入到自己的工程里。

<project>
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.alibaba.union</groupId>
  <artifactId>union-demo</artifactId>
  <version>1.0.0-SNAPSHOT</version>
  <dependencyManagement>
    <dependencies>
      <dependency>
        <groupId>com.alibaba.union</groupId>
        <artifactId>union-boot-starter-bom</artifactId>
        <version>1.0.0-RELEASE</version>
        <type>pom</type>
        <scope>import</scope>
      </dependency>
    </dependencies>
  </dependencyManagement>
</project>

这样,虽然多建了一个过渡性工程,但定制依赖项版本同继承时一样简单。

5.4 自定义Starter

下面以本人封装的Tddl组件为例:
1、创建union-tddl-spring-boot-starter工程
2、引入spring-boot和pandora-boot的配置

<dependencyManagement>
    <dependencies>
        <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-dependencies</artifactId>
        <version>${spring-boot.version}</version>
        <type>pom</type>
        <scope>import</scope>
        </dependency>
        <dependency>
        <groupId>com.taobao.pandora</groupId>
        <artifactId>pandora-boot-starter-bom</artifactId>
        <version>${pandora-boot.version}</version>
        <type>pom</type>
        <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

3、定义一个pojo用来接收properties中配置的信息

@ConfigurationProperties(prefix = "spring.tddl")
public class TddlProperties {
    private String mapperPath;
    private String typeAliasesPackage;
    private String basePackage;
    ......
}

4、创建AutoConfiguration注册Bean

@Configuration
@EnableConfigurationProperties(TddlProperties.class)
public class TddlAutoConfiguration implements EnvironmentAware {
    @Autowired
    private TddlProperties properties;
    @Bean(name = "sqlSessionFactory")
    public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception {
        SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();
        factoryBean.setDataSource(dataSource);
        factoryBean.setTypeAliasesPackage(properties.getTypeAliasesPackage());
        return factoryBean.getObject();
    }
}

5、在新建的spring.factories文件中配置自动启动类

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
  com.alibaba.union.tddl.TddlAutoConfiguration

6、在新建的spring.provides文件中配置Starter的名字

provides: union-tddl-spring-boot-starter

7、发布你的starter
更多详情请参考以下代码:
Starter源码
Starter示例

6 参考资料

SpringBoot官网
AE-SpringBoot Wiki
PandoraBoot Wiki
UnionBoot Wiki