什么是Spring Boot ?
Spring Boot 是由 Pivotal 团队提供的全新框架,其设计目的是用来简化新 Spring 应用的初始搭建以及开发过程。该框架使用了特定的方式来进行配置,从而使开发人员不再需要定义样板化的配置。spring Boot采用约定优于配置的方式,大量的减少了配置文件的使用。
Spring Boot可以理解成是Spring框架的扩展,能够简化各框架的配置文件;快速构建web应用;而且内置了tomcat,web项目无需打包部署,可以直接运行,也可以打成jar包,直接在线上环境运行。
什么是“约定优于配置”?
“约定优于配置”,其实一种按约定编程的软件设计范式,目的在于减少软件开发人员在工作中的各种繁琐的配置。
Spring Boot的产生很好的遵循了“约定优于配置”这一理念,这才使得它变得如此简单、快速和便捷。那这一理念在Spring Boot中的具体表现有哪些呢?
- 一系列的Starter简化框架的整合
- 运行方式采用内置tomcat容器,可以使用jar包部署项目
- 默认配置文件properties和yaml,语法简洁、功能强大
-
什么是Starter ?
Spring Boot中的Starter可以理解成是一系列依赖的组合,Spring Boot还帮助我们完成了它们之间的配置。
例如,我们想在Spring Boot中使用Spring MVC。如果不是Spring Boot项目,我们需要引入spring-web、spring-webmvc、spring-aop等一系列依赖。但是在Spring Boot项目中,只需要引入spring-boot-starter-web即可。<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
Starter的依赖命名都遵循相同的规则:spring-boot-starter-*。例如常用的Starter有:
spring-boot-starter-data-jpa
- spring-boot-starter-redis
- spring-boot-starter-security
- spring-boot-starter-test
- spring-boot-starter-thymeleaf
- … …
*-spring-boot-starter: 第三方为我们提供的简化开发的场景启动器。
所有场景启动器最底层的依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<version>2.3.4.RELEASE</version>
<scope>compile</scope>
</dependency>
Spring Boot的特点
- Create stand-alone Spring applications
- 创建独立Spring应用
- Embed Tomcat, Jetty or Undertow directly (no need to deploy WAR files)
- 内嵌web服务器
- Provide opinionated ‘starter’ dependencies to simplify your build configuration
- 自动starter依赖,简化构建配置
- Automatically configure Spring and 3rd party libraries whenever possible
- 自动配置Spring以及第三方功能
- Provide production-ready features such as metrics, health checks, and externalized configuration
- 提供生产级别的监控、健康检查及外部化配置
- Absolutely no code generation and no requirement for XML configuration
- 无代码生成、无需编写XML
SpringBoot是整合Spring技术栈的一站式框架
SpringBoot是简化Spring技术栈的快速开发脚手架
自动配置原理
依赖管理
依赖管理这个是我们的项目pom.xml编写的,管理项目的资源过滤及插件
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.4.RELEASE</version>
</parent>
spring-boot-starter-parent的工程又依赖了spring-boot-dependencies,
管理SpringBoot应用里面所有依赖版本的地方,SpringBoot的版本控制中心,
以后我们导入依赖默认是不需要写版本;但是如果导入的包没有在依赖中管理着就需要手动配置版本了;
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.3.4.RELEASE</version>
</parent>
修改默认版本号
1、查看spring-boot-dependencies里面规定当前依赖的版本 用的 key。
2、在当前项目里面重写配置在properties
节点下修改版本号
<properties>
<mysql.version>5.1.43</mysql.version>
</properties>
自动配置
常用框架对应的JavaConfig类都已经编写好了,springboot启动的时候会一个一个的进行读取,读取时会先根据条件注解进行判断,看是否满足条件,满足条件后才会读取配置类然后去配置对应的框架。
1. Springboot启动后,读取程序的启动类时,就会读取到@SpringBootApplication
注解
@SpringBootApplication
public class DateDemoApplication {
public static void main(String[] args) {
SpringApplication.run(DateDemoApplication.class, args);
}
}
2. @SpringBootApplication
注解又包含了 @EnableAutoConfiguration
注解
// 注解的适用范围,其中TYPE用于描述类、接口(包括包注解类型)或enum声明
@Target(ElementType.TYPE)
// 注解的生命周期,保留到class文件中(三个生命周期)
@Retention(RetentionPolicy.RUNTIME)
// 表明这个注解应该被javadoc记录
@Documented
// 子类可以继承该注解
@Inherited
// 继承了Configuration,表示当前是注解类
@SpringBootConfiguration
// 开启springboot的注解功能,springboot的四大神器之一,其借助@import的帮助
@EnableAutoConfiguration
// 扫描路径设置
@ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {
/**
* Exclude specific auto-configuration classes such that they will never be applied.
* @return the classes to exclude
*/
@AliasFor(annotation = EnableAutoConfiguration.class)
Class<?>[] exclude() default {};
...
}
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Configuration
public @interface SpringBootConfiguration {
...
}
@EnableAutoConfiguration
注解导入了AutoConfigurationImportSelector类,
即@Import(AutoConfigurationImportSelector.class)
@EnableAutoConfiguration告诉SpringBoot开启自动配置功能,这样自动配置才能生效; ```java @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited @AutoConfigurationPackage // @Import({AutoConfigurationImportSelector.class}) :给容器导入组件 ; // AutoConfigurationImportSelector :自动配置导入选择器 @Import(AutoConfigurationImportSelector.class) public @interface EnableAutoConfiguration {/**
- Environment property that can be used to override when auto-configuration is
enabled. */ String ENABLED_OVERRIDE_PROPERTY = “spring.boot.enableautoconfiguration”;
…
}
4. `@AutoConfigurationPackage` :**自动配置包**
```java
// @import :Spring底层注解@import , 给容器中导入一个组件
// Registrar.class 作用:将主启动类的所在包及包下面所有子包里面的所有组件扫描到Spring容器 ;
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@Import(AutoConfigurationPackages.Registrar.class)
public @interface AutoConfigurationPackage {
...
}
AutoConfigurationImportSelector.class中,定义了一个方法getCandidateConfigurations,进入getCandidateConfigurations方法,getCandidateConfigurations会到classpath下的读取META-INF/spring.factories文件的配置
protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
List<String> configurations = SpringFactoriesLoader.loadFactoryNames(getSpringFactoriesLoaderFactoryClass(),
getBeanClassLoader());
Assert.notEmpty(configurations, "No auto configuration classes found in META-INF/spring.factories. If you "
+ "are using a custom packaging, make sure that file is correct.");
return configurations;
}
spring.factories文件在spring-boot-autoconfigure-2.3.7.RELEASE.jar的META-INF中,spring.factories文件中声明了很多java配置类,但是每个配置类都是需要满足一定的条件才会执行(例如: @ConditionalOnClass 、 @ConditionalOnProperty、 @ConditionalOnMissingBean等)
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\
org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\
org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration,\
org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration,\
org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration,\
org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration,\
org.springframework.boot.autoconfigure.context.ConfigurationPropertiesAutoConfiguration,\
org.springframework.boot.autoconfigure.context.LifecycleAutoConfiguration,\
org.springframework.boot.autoconfigure.context.MessageSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration,\
org.springframework.boot.autoconfigure.couchbase.CouchbaseAutoConfiguration,\
...
- 随便打开一个自动配置文件,比如说
WebMvcAutoConfiguration.class
```java @Configuration(proxyBeanMethods = false) @ConditionalOnWebApplication(type = Type.SERVLET) @ConditionalOnClass({ Servlet.class, DispatcherServlet.class, WebMvcConfigurer.class }) @ConditionalOnMissingBean(WebMvcConfigurationSupport.class) @AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE + 10) @AutoConfigureAfter({ DispatcherServletAutoConfiguration.class, TaskExecutionAutoConfiguration.class,
public class WebMvcAutoConfiguration {ValidationAutoConfiguration.class })
}
``
从
WebMvcAutoConfiguration`这个类中使用的注解可以看出,要完成自动配置是有依赖条件的。
这些是springboot特有的,常见的条件依赖注解有:
@ConditionalOnSingleCandidate,仅在当前上下文中存在某个bean时,才会实例化这个Bean。
@ConditionalOnClass,某个class位于类路径上,才会实例化这个Bean。
@ConditionalOnExpression,当表达式为true的时候,才会实例化这个Bean。
@ConditionalOnMissingBean,仅在当前上下文中不存在某个bean时,才会实例化这个Bean。
@ConditionalOnMissingClass,某个class在类路径上不存在的时候,才会实例化这个Bean。
@ConditionalOnNotWebApplication,不是web应用时才会实例化这个Bean。
@AutoConfigureAfter,在某个bean完成自动配置后实例化这个bean。
@AutoConfigureBefore,在某个bean完成自动配置前实例化这个bean。
所以,自动配置真正实现是从classpath中搜寻所有的META-INF/spring.factories配置文件 ,并将其中对应的 org.springframework.boot.autoconfigure. 包下的配置项,通过反射实例化为对应标注了 @Configuration的JavaConfig形式的IOC容器配置类 , 然后将这些都汇总成为一个实例并加载到IOC容器中。\
总结
1、@Configuration&与@Bean->基于java代码的bean配置
2、@Conditional->设置自动配置条件依赖
3、@EnableConfigurationProperties与@ConfigurationProperties->读取配置文件转换为bean。
4、@EnableAutoConfiguration、@AutoConfigurationPackage 与@Import->实现bean发现与加载。
5、@EnableAutoConfiguration自动配置从classpath中搜寻所有的META-INF/spring.factories配置文件,并将其中org.springframework.boot.autoconfigure.EnableutoConfiguration对应的配置项通过反射(Java Refletion)实例化为对应的标注了@Configuration的JavaConfig形式的IoC容器配置类,然后汇总为一个并加载到IoC容器。
springboot启动加载所有的配置类(127个),按需加载所需配置类。
**