springboot简介
springboot之前
-
要集成一个spring框架,开启spring的特性需要进行一系列的显示配置比如:事务管理、MVC、基于Thymeleaf的WEB视图,配置Servlet和过滤器(比如Spring的DispatcherServlet)同样需要在web.xml或Servlet初始化代码里进行显式配置
-
项目的依赖管理也是件吃力不讨好的事情。决定项目里要用哪些库就已经够让人头痛的了,你还要知道这些库的哪个版本和其他库不会有冲突,这难题实在太棘手
以上这些无论业务代码是多少,这些都是不可缺少,springboot的出现让这一切变得简单
springboot精要
- 起步依赖,告诉springboot需要什么功能,他就能引入需要的库
- 自动配置,针对很多spring应用程序常见的应用功能,springboot能自动提供相关配置
- 命令行界面(springboot CGI),很少使用
- Actuator,提供在运行时检视应用程序内部情况的能力,很少使用
起步依赖分析
springboot通过提供众多起步依赖降低项目依赖的复杂度,起步依赖本质上是一个Maven项目对象依赖,定义了对其他库的传递依赖,比如springboot常用的依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
可以通过mvn dependency:tree查看依赖树
- org.springframework.boot:spring-boot-starter-web:jar:2.1.2.RELEASE:compile
+- org.springframework.boot:spring-boot-starter:jar:2.1.2.RELEASE:compile
| +- org.springframework.boot:spring-boot:jar:2.1.2.RELEASE:compile
| +- org.springframework.boot:spring-boot-autoconfigure:jar:2.1.2.RELEASE:compile
| +- org.springframework.boot:spring-boot-starter-logging:jar:2.1.2.RELEASE:compile
| | +- ch.qos.logback:logback-classic:jar:1.2.3:compile
| | | +- ch.qos.logback:logback-core:jar:1.2.3:compile
| | | \- org.slf4j:slf4j-api:jar:1.7.25:compile
| | +- org.apache.logging.log4j:log4j-to-slf4j:jar:2.11.1:compile
| | | \- org.apache.logging.log4j:log4j-api:jar:2.11.1:compile
| | \- org.slf4j:jul-to-slf4j:jar:1.7.25:compile
| +- javax.annotation:javax.annotation-api:jar:1.3.2:compile
| +- org.springframework:spring-core:jar:5.1.4.RELEASE:compile
| | \- org.springframework:spring-jcl:jar:5.1.4.RELEASE:compile
| \- org.yaml:snakeyaml:jar:1.23:runtime
+- org.springframework.boot:spring-boot-starter-json:jar:2.1.2.RELEASE:compile
| +- com.fasterxml.jackson.core:jackson-databind:jar:2.9.8:compile
| | +- com.fasterxml.jackson.core:jackson-annotations:jar:2.9.0:compile
| | \- com.fasterxml.jackson.core:jackson-core:jar:2.9.8:compile
| +- com.fasterxml.jackson.datatype:jackson-datatype-jdk8:jar:2.9.8:compile
| +- com.fasterxml.jackson.datatype:jackson-datatype-jsr310:jar:2.9.8:compile
| \- com.fasterxml.jackson.module:jackson-module-parameter-names:jar:2.9.8:compile
+- org.springframework.boot:spring-boot-starter-tomcat:jar:2.1.2.RELEASE:compile
| +- org.apache.tomcat.embed:tomcat-embed-core:jar:9.0.14:compile
| +- org.apache.tomcat.embed:tomcat-embed-el:jar:9.0.14:compile
| \- org.apache.tomcat.embed:tomcat-embed-websocket:jar:9.0.14:compile
+- org.hibernate.validator:hibernate-validator:jar:6.0.14.Final:compile
| +- javax.validation:validation-api:jar:2.0.1.Final:compile
| +- org.jboss.logging:jboss-logging:jar:3.3.2.Final:compile
| \- com.fasterxml:classmate:jar:1.4.0:compile
+- org.springframework:spring-web:jar:5.1.4.RELEASE:compile
| \- org.springframework:spring-beans:jar:5.1.4.RELEASE:compile
\- org.springframework:spring-webmvc:jar:5.1.4.RELEASE:compile
+- org.springframework:spring-aop:jar:5.1.4.RELEASE:compile
+- org.springframework:spring-context:jar:5.1.4.RELEASE:compile
\- org.springframework:spring-expression:jar:5.1.4.RELEASE:compile
排除起步依赖中的某一项直接加入exclusions标签
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>com.fasterxml.jackson.core</groupId>
</exclusion>
</exclusions>
</dependency>
也可以不使用起步依赖中的版本,使用其他版本。MAVEN总会使用最近的依赖,在项目的构建说明文件里增加的这个依赖,会覆盖传递依赖引入的另外一个依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.4.3</version>
</dependency>
自动配置分析
Condition
- 实现Condition接口,实现其抽象方法
//true满足条件,false不满足条件 boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata); - 在声明配置中判断是否生效,如下判断是否加载为一个Bean的代码片段
@Bean //matches接口返回true则加载为bean @Conditional({PetCondition.class}) public Dog dog(){ return new Dog(); }
类Condition注解
他们和Condition有类似的功能,算是对Condition的一个扩展,满足了条件就生效
- @ConditionalOnBean——配置了某个特定的Bean
- @ConditionalOnMissingBean——没有配置特定的Bean
- @ConditionalOnClass——Classpath里有指定的类
- @ConditionalOnMissingClass——Classpath里缺少指定的类
- @ConditionalOnExpression——给定的SpEL表达式计算结果为true
- @ConditionalOnJava——java的版本匹配特定值或者一个范围值
- @ConditionalOnJndi——参数中给定的JNDI位置必须存在一个,如果没有参数则要JNDI InitialContext
- @ConditionalOnProperty——指定配置属性要有一个明确的值
- @ConditionalOnResource——Classpath里有指定的资源
- @ConditionalOnWebApplication——这是一个Web应用程序
- @ConditionalOnNotWebApplication——这不是一个Web应用程序
@SpringBootApplication
-
这是springboot的主类启动注解,一般如下
@SpringBootApplication public class SpringBootDemoApplication extends SpringBootServletInitializer { public static void main(String[] args) { SpringApplication.run(SpringBootDemoApplication.class, args); } } -
@SpringBootApplication声明如下
@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited @SpringBootConfiguration @EnableAutoConfiguration @ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class), @Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) }) public @interface SpringBootApplication { //若干属性省略,来修改父注解的属性值 } -
父注解@SpringBootConfiguration等同于@Configuration注解,声明为一个配置类
-
父注解@ComponentScan配置额外的包扫描路径
-
父注解@EnableAutoConfiguration为主要的自动配置类注解,定义如下
@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited @AutoConfigurationPackage @Import(AutoConfigurationImportSelector.class) public @interface EnableAutoConfiguration { //省略若干属性 } -
@AutoConfigurationPackage注解主要是自动加载某些jar包的bean,定义如下
@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited @Import(AutoConfigurationPackages.Registrar.class) public @interface AutoConfigurationPackage { } @Override public void registerBeanDefinitions(AnnotationMetadata metadata,BeanDefinitionRegistry registry) { //它其实返回了当前主程序类的 同级以及子级 的包组件 //也就是为什么我们一般会将主类放在最外面的原因 register(registry, new PackageImport(metadata).getPackageName()); } -
@Import(AutoConfigurationImportSelector.class)引入自动配置类包,相关的执行代码如下
//加载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中声明的类,都是遵循的Condition来决定是否加载成为bean,例如DataSourceAutoConfiguration类,部分定义如下
@Configuration @ConditionalOnClass({ DataSource.class, EmbeddedDatabaseType.class }) @EnableConfigurationProperties(DataSourceProperties.class) @Import({ DataSourcePoolMetadataProvidersConfiguration.class, DataSourceInitializationConfiguration.class }) public class DataSourceAutoConfiguration { @Configuration @Conditional(EmbeddedDatabaseCondition.class) @ConditionalOnMissingBean({ DataSource.class, XADataSource.class }) @Import(EmbeddedDataSourceConfiguration.class) protected static class EmbeddedDatabaseConfiguration { } @Configuration @Conditional(PooledDataSourceCondition.class) @ConditionalOnMissingBean({ DataSource.class, XADataSource.class }) @Import({ DataSourceConfiguration.Hikari.class, DataSourceConfiguration.Tomcat.class, DataSourceConfiguration.Dbcp2.class, DataSourceConfiguration.Generic.class, DataSourceJmxConfiguration.class }) protected static class PooledDataSourceConfiguration { } }
自定义配置
覆盖自动配置
在自动配置中,有很多都是基于ConditionalOnMissingBean来判断的,当我们自定义的这个bean,他就不会采用自动配置,如DataSourceAutoConfiguration中的部分配置:
@Configuration
@Conditional(EmbeddedDatabaseCondition.class)
@ConditionalOnMissingBean({ DataSource.class, XADataSource.class })
@Import(EmbeddedDataSourceConfiguration.class)
protected static class EmbeddedDatabaseConfiguration {
}
通过属性文件外置配置
Spring Boot应用程序有多种设置途径。Spring Boot能从多种属性源获得属性,高优先级可以覆盖低优先级的属性,优先级从高到低排序如下:
- 命令行参数
java -jar readinglist-0.0.1-SNAPSHOT.jar --spring.main.show-banner=false - java:comp/env里的JNDI属性
- JVM系统属性
- 操作系统环境变量
export spring_main_show_banner=false - 随机生成的带random.*前缀的属性(在设置其他属性时,可以引用它们,比如${random. long})
- 应用程序以外的application.properties或者appliaction.yml文件
spring.main.show-banner=false spring: main: show-banner: false - 打包在应用程序内的application.properties或者appliaction.yml文件
- 通过@PropertySource标注的属性源
- 默认属性
application.properties和application.yml文件能放在以下四个位置,优先级从高到低如下
- 外置,在相对于应用程序运行目录的/config子目录里
- 外置,在应用程序运行的目录里
- 内置,在config包内
- 内置,在Classpath根目录