什么是 Spring Boot
Spring Boot 基本上是 Spring 框架的扩展,它消除了设置 Spring 应用程序所需的复杂例行配置。我们在使用 Spring 框架的时候,我们接触得比较多的应该是 Spring MVC、 IOC 、 DI 、AOP 等等,而这些框架在使用的过程中会需要配置大量的 XML,或者需要做很多繁琐的配置。Spring Boot 可以帮助我们快速搭建一个基于 Spirng 框架以及 Spring 生态体系的应用解决方案。
- 创建独立的 Spring 应用程序
- 直接嵌入 Tomcat,Jetty 或 Undertow(无需部署 WAR 文件),java -jar 就可以运行
- 提供 starter 依赖来简化你自己的配置
- 自动装配 Spring 和第三方的依赖
- 提供可用于生产的功能,例如指标,运行状况检查和外部化配置,比如 Actuator
- 完全没有代码生成,也不需要 XML 配置
约定大于配置
- maven 的目录结构,默认有 resources 文件夹存放配置文件,默认打包方式为 jar
- spring-boot-starter-web 中默认包含 spring mvc 相关依赖以及内置的 tomcat 容器,使得构建一个 web 应用更加简单
- 默认提供 application.properties/yml 文件
- 默认通过 spring.profiles.active 属性来决定运行环境时读取的配置文件
- EnableAutoConfiguration 默认对于依赖的 starter 进行自动装配
自动装配
@SpringBootApplication实际上是一个复合注解,主要由以下构成:
@Configuration
@Configuration是 JavaConfig 形式的基于 Spring IOC 容器的配置类使用的一种注解。所以在启动类里面标注了 @Configuration,意味着它其实也是一个 IoC 容器的配置类。
传统意义上的 Spring 应用都是基于 xml 形式来配置 bean 的依赖关系。但是从 Spring3 开始,Spring 就支持了两种 bean 的配置方式,一种是基于 xml 文件方式,另一种就是 JavaConfig,任何一个标注了 @Configuration 的 Java 类定义都是一个 JavaConfig 配置类。而在这个配置类中,任何标注了 @Bean 的方法,它的返回值都会作为 Bean 定义注册到 Spring 的 IoC 容器,方法名默认成为这个 Bean 的 id。然后通过 spring 容器在启动的时候,把 Bean 进行初始化并且,如果 Bean 之间存在依赖关系,则分析这些已经在 IoC 容器中的 Bean 根据依赖关系进行组装。
@ComponentScan
@ComponentScan 就是扫包,相当于 xml 配置文件中的context:component-scan 。
它的主要作用就是扫描指定路径下的标识了需要装配的类,自 动装配到 Spring 的 IoC 容器中。
标识需要装配的类的形式主要是:@Component、@Repository、@Service、@Controller 这类的注解标识的类。(注:@Repository、@Service、@Controller 的底层还是 @Component)。ComponentScan 默认会扫描当前 package 下的的所有加了相关注解标识的类到 IoC 容器中。
@EnableAutoConfiguration
@EnableAutoConfiguration 是 Spring Boot 的灵魂。从 Spring3.1 开始,提供了一系列的 @Enable 开头的注解,它是在 JavaConfig 框架上更进一步的完善,使用户在使用 Spring 相关的框架避免配置大量的代码从而降低使用的难度。
每一个涉及到 Enable 开头的注解,都会带有一个 @Import 的注解, @EnableAutoConfiguration 也不例外。
@Import 对应 XML 形式下的 ,就是导入资源,把多个分布在不同容器下的配置合并在一个配置中。@Import 注解可以配置三种不同的 class :
普通 Bean 或者带有 @Configuration 的配置文件
实现 ImportSelector 接口进行动态注入
实现 ImportBeanDefinitionRegistrar 接口进行动态注入
这里导入的是第二种 importSelector,这是一种动态注入 Bean 的技术。其中AutoConfigurationImportSelector实现了 ImportSelector 接口。借助AutoConfigurationImportSelector,@EnableAutoConfiguration帮助SpringBoot应用将所有符合条件的@Configuration配置都加载到当前SpringBoot创建并使用的IoC容器。
在AutoConfigurationImportSelector类中可以看到通过 SpringFactoriesLoader.loadFactoryNames()把 spring-boot-autoconfigure.jar/META-INF/spring.factories中每一个xxxAutoConfiguration文件都加载到容器中,spring.factories文件里每一个xxxAutoConfiguration文件一般都会有下面的条件注解:
- @ConditionalOnClass : classpath中存在该类时起效
- @ConditionalOnMissingClass : classpath中不存在该类时起效
- @ConditionalOnBean : DI容器中存在该类型Bean时起效
- @ConditionalOnMissingBean : DI容器中不存在该类型Bean时起效
- @ConditionalOnSingleCandidate : DI容器中该类型Bean只有一个或@Primary的只有一个时起效
- @ConditionalOnExpression : SpEL表达式结果为true时
- @ConditionalOnProperty : 参数设置或者值一致时起效
- @ConditionalOnResource : 指定的文件存在时起效
- @ConditionalOnJndi : 指定的JNDI存在时起效
- @ConditionalOnJava : 指定的Java版本存在时起效
- @ConditionalOnWebApplication : Web应用环境下起效
- @ConditionalOnNotWebApplication : 非Web应用环境下起效
SpringFactoriesLoader
SpringFactoriesLoader属于Spring框架私有的一种扩展方案(类似于Java的SPI方案java.util.ServiceLoader),其主要功能就是从指定的配置文件META-INF/spring-factories加载配置,spring-factories是一个典型的java properties文件,只不过Key和Value都是Java类型的完整类名。
对于@EnableAutoConfiguration来说,SpringFactoriesLoader的用途稍微不同一些,其本意是为了提供SPI扩展的场景,而在@EnableAutoConfiguration场景中,它更多提供了一种配置查找的功能支持,即根据@EnableAutoConfiguration的完整类名org.springframework.boot.autoconfig.EnableAutoConfiguration作为查找的Key,获得对应的一组@Configuration类。
SpringFactoriesLoader是一个抽象类,类中定义的静态属性定义了其加载资源的路径public static final String FACTORIES_RESOURCE_LOCATION = “META-INF/spring.factories”,此外还有三个静态方法:
- loadFactories:加载指定的factoryClass并进行实例化。
- loadFactoryNames:加载指定的factoryClass的名称集合。
- instantiateFactory:对指定的factoryClass进行实例化。
loadFactories方法首先获取类加载器,然后调用loadFactoryNames方法获取所有的指定资源的名称集合、接着调用instantiateFactory方法实例化这些资源类并将其添加到result集合中。最后调用AnnotationAwareOrderComparator.sort方法进行集合的排序。
SpringBoot starter
SpringBoot中的starter是一种非常重要的机制,能够抛弃以前繁杂的配置,将其统一集成进starter,应用者只需要在maven中引入starter依赖,SpringBoot就能自动扫描到要加载的信息并启动相应的默认配置。
starter让我们摆脱了各种依赖库的处理,需要配置各种信息的困扰。SpringBoot会自动通过classpath路径下的类发现需要的Bean,并注册进IOC容器。SpringBoot提供了针对日常企业应用研发各种场景的spring-boot-starter依赖模块。所有这些依赖模块都遵循着约定成俗的默认配置,并允许我们调整这些配置,即遵循“约定大于配置”的理念。
starter的实现方法
- 创建一个starter项目,Spring 官方定义的 starter 通常命名遵循的格式为 spring-boot-starter-{name}。
- 创建一个ConfigurationProperties用于保存你的配置信息。
- 创建一个AutoConfiguration,引用定义好的配置信息。在AutoConfiguration中实现所有starter应该完成的操作,并且把这个类加入spring.factories配置文件中进行声明。
- 打包项目,之后在一个SpringBoot项目中引入该项目依赖。
引入的依赖
<dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-autoconfigure</artifactId></dependency>
</dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build>
spring-boot-autoconfigure中包含大量核心注解,包含条件注解等。
创建properties属性类,用于读取属性
@ConfigurationProperties(prefix = "com.test")
public class TestServiceProperties {private String name = "test";public String getName() {return name;}public void setName(String name) {this.name = name;}}
@ConfigurationProperties配置此注解可以自动导入application.properties配置文件中的属性,前提需要指定属性前缀prefix。如果application.properties文件中未指定相应属性,便使用默认的,如上name=“test”。
创建配置类
public class TestServiceConfiguration {private String name;public String getName() {return "name is " + name;}public void setName(String name) {this.name = name;}
}
创建自动配置类
@Configuration
@EnableConfigurationProperties(TestServiceProperties.class)
@ConditionalOnClass(TestServiceConfiguration.class)
@ConditionalOnProperty(prefix = "com.test", value = "enabled", matchIfMissing = true)
public class TestServiceAutoConfiguration {@Autowiredprivate TestServiceProperties testServiceProperties;@Bean@ConditionalOnMissingBean(TestServiceConfiguration.class)public TestServiceConfiguration testServiceConfiguration() {TestServiceConfiguration testService = new TestServiceConfiguration();TestService.setName(testServiceProperties.getName());return testService;}
}
- @Configuration:表明此类是一个配置类,将变为一个bean被spring进行管理。
- @EnableConfigurationProperties:启用属性配置,将读取TestServiceProperties里面的属性。
- @ConditionalOnClass:当类路径下面有TestServiceConfiguration此类时,自动配置。
- @ConditionalOnProperty:判断指定的属性是否具备指定的值。
- @ConditionalOnMissingBean:当容器中没有指定bean时,创建此bean。
配置类注册
在resources文件夹下面新建一个META-INF文件,并在下面创建spring.factories文件,将配置类进行注册。
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\com.test.TestServiceAutoConfiguration
使用
自定义的starter编写完毕,执行mvn clean install将项目打成一个jar包。新建一个springboot项目,在pom文件中添加刚刚打包的jar。
在application.properties添加
com.test.name=test