起步依赖分析

分析spring-boot-starter-parent

按住Ctrl点击pom.xml中的spring-boot-starter-parent,跳转到了spring-boot-starter-parent的pom.xml,xml配置如下(只摘抄了部分重点配置):

<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.2.5.RELEASE</version>
<relativePath>../../spring-boot-dependencies</relativePath>
</parent>

按住Ctrl点击pom.xml中的spring-boot-starter-dependencies,跳转到了spring-boot-starter-dependencies的pom.xml,xml配置如下(只摘抄了部分重点配置):

<properties>
<activemq.version>5.15.11</activemq.version>
<antlr2.version>2.7.7</antlr2.version>
<appengine-sdk.version>1.9.78</appengine-sdk.version>
<artemis.version>2.10.1</artemis.version>
<aspectj.version>1.9.5</aspectj.version>
<assertj.version>3.13.2</assertj.version>
<atomikos.version>4.0.6</atomikos.version>
<awaitility.version>4.0.2</awaitility.version>
<bitronix.version>2.1.4</bitronix.version>
<build-helper-maven-plugin.version>3.0.0</build-helper-maven-plugin.version>
<byte-buddy.version>1.10.8</byte-buddy.version>
... .... ... <dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot</artifactId>
<version>2.2.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-test</artifactId>
<version>2.2.5.RELEASE</version>
</dependency>
... ... ...
</dependencies>
</dependencyManagement>
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.johnzon</groupId>
<artifactId>johnzon-maven-plugin</artifactId>
<version>${johnzon.version}</version>
</plugin>
<plugin>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-maven-plugin</artifactId>
<version>${kotlin.version}</version>
</plugin>
<plugin>
<groupId>org.jooq</groupId>
<artifactId>jooq-codegen-maven</artifactId>
<version>${jooq.version}</version>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>2.2.5.RELEASE</version>
</plugin>
... ... ...
</plugins>
</pluginManagement>
</build>

从上面的spring-boot-starter-dependencies的pom.xml中我们可以发现,一部分坐标的版本、依赖管理、插件管理已经定义好,所以我们的SpringBoot工程继承spring-boot-starter-parent后已经具备版本锁定等配置了。所以起步依赖的作用就是进行依赖的传递。

分析spring-boot-starter-web

按住Ctrl点击pom.xml中的spring-boot-starter-web,跳转到了spring-boot-starter-web的pom.xml,xml配置如下(只摘抄了部分重点配置):

<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starters</artifactId>
<version>2.2.5.RELEASE</version>
</parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>2.2.5.RELEASE</version>
<name>Spring Boot Web Starter</name>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<version>2.2.5.RELEASE</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-json</artifactId>
<version>2.2.5.RELEASE</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<version>2.2.5.RELEASE</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
<version>2.2.5.RELEASE</version>
<scope>compile</scope>
<exclusions>
<exclusion>
<artifactId>tomcat-embed-el</artifactId>
<groupId>org.apache.tomcat.embed</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>5.2.4.RELEASE</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.2.4.RELEASE</version>
<scope>compile</scope>
</dependency>
</dependencies>
</project>

自动配置原理解析

按住Ctrl点击查看启动类MySpringBootApplication上的注解@SpringBootApplication

package xyz.ytfs;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication
public class SpringbootQuick2Application { public static void main(String[] args) {
SpringApplication.run(SpringbootQuick2Application.class, args);
} }
/*
* Copyright 2012-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/ package org.springframework.boot.autoconfigure; import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; import org.springframework.boot.SpringBootConfiguration;
import org.springframework.boot.context.TypeExcludeFilter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.ComponentScan.Filter;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.FilterType;
import org.springframework.core.annotation.AliasFor;
import org.springframework.data.repository.Repository; /**
* Indicates a {@link Configuration configuration} class that declares one or more
* {@link Bean @Bean} methods and also triggers {@link EnableAutoConfiguration
* auto-configuration} and {@link ComponentScan component scanning}. This is a convenience
* annotation that is equivalent to declaring {@code @Configuration},
* {@code @EnableAutoConfiguration} and {@code @ComponentScan}.
*
* @author Phillip Webb
* @author Stephane Nicoll
* @author Andy Wilkinson
* @since 1.2.0
*/
@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 { /**
* Exclude specific auto-configuration classes such that they will never be applied.
* @return the classes to exclude
*/
@AliasFor(annotation = EnableAutoConfiguration.class)
Class<?>[] exclude() default {}; /**
* Exclude specific auto-configuration class names such that they will never be
* applied.
* @return the class names to exclude
* @since 1.3.0
*/
@AliasFor(annotation = EnableAutoConfiguration.class)
String[] excludeName() default {};
... ... ... }

其中,

@SpringBootConfiguration:等同与@Configuration,既标注该类是Spring的一个配置类

@EnableAutoConfiguration:SpringBoot自动配置功能开启

按住Ctrl点击查看注解@EnableAutoConfiguration

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {
... ... ...
}

其中,@Import(AutoConfigurationImportSelector.class) 导入了AutoConfigurationImportSelector类

按住Ctrl点击查看AutoConfigurationImportSelector源码

public String[] selectImports(AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return NO_IMPORTS;
}
AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader
.loadMetadata(this.beanClassLoader);
AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry(autoConfigurationMetadata,
annotationMetadata);
return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
} 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;
}

其中,SpringFactoriesLoader.loadFactoryNames 方法的作用就是从META-INF/spring.factories文件中读取指定类对应的类名称列表

spring.factories 文件中有关自动配置的配置信息如下:

... ... ...

org.springframework.boot.autoconfigure.web.reactive.function.client.ClientHttpConnectorAutoConfiguration,\
org.springframework.boot.autoconfigure.web.reactive.function.client.WebClientAutoConfiguration,\
org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration,\
org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration,\
org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration,\
org.springframework.boot.autoconfigure.web.servlet.HttpEncodingAutoConfiguration,\
org.springframework.boot.autoconfigure.web.servlet.MultipartAutoConfiguration,\
org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration,\ ... ... ...

上面配置文件存在大量的以Configuration为结尾的类名称,这些类就是存有自动配置信息的类,而SpringApplication在获取这些类名后再加载

我们以ServletWebServerFactoryAutoConfiguration为例来分析源码:

@Configuration(proxyBeanMethods = false)
@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE)
@ConditionalOnClass(ServletRequest.class)
@ConditionalOnWebApplication(type = Type.SERVLET)
@EnableConfigurationProperties(ServerProperties.class)
@Import({ ServletWebServerFactoryAutoConfiguration.BeanPostProcessorsRegistrar.class,
ServletWebServerFactoryConfiguration.EmbeddedTomcat.class,
ServletWebServerFactoryConfiguration.EmbeddedJetty.class,
ServletWebServerFactoryConfiguration.EmbeddedUndertow.class })
public class ServletWebServerFactoryAutoConfiguration {
... ... ...
}

其中,

@EnableConfigurationProperties(ServerProperties.class) 代表加载ServerProperties服务器配置属性类

进入ServerProperties.class源码如下:

@ConfigurationProperties(prefix = "server", ignoreUnknownFields = true)
public class ServerProperties { /**
* Server HTTP port.
*/
private Integer port; /**
* Network address to which the server should bind.
*/
private InetAddress address;; ... ... ... }

其中,

prefix = "server" 表示SpringBoot配置文件中的前缀,SpringBoot会将配置文件中以server开始的属性映射到该类的字段中。映射关系如下

最新文章

  1. phpmyadmin #1045 - Access denied for user &#39;root&#39;@&#39;localhost&#39; (using password: NO)
  2. CSS 颜色代码大全
  3. 执行HQL语句出现Remember that ordinal parameters are 1-based
  4. 用webdriver+phantomjs实现无浏览器的自动化过程
  5. JS生成UUID的方法实例
  6. JavaScript 阶段总结
  7. dede图片横向滚动
  8. 码农谷 球从M米高度自由下落第N次落地时反弹的高度
  9. CSDN问答频道“华章杯”7月排行榜活动开始,丰厚奖品等你拿
  10. DBCP数据源
  11. Matlab spline
  12. R语言-图形初阶
  13. 多路分支----switch语句
  14. day43-python消息队列二-queue模块
  15. flask 第七章 简陋版智能玩具 +MongoDB初识和基本操作
  16. 微信自带浏览器不支持form表单post提交方案解决
  17. 【转】wpf中的xmlns命名空间为什么是一个网址,代表了什么意思
  18. 比较Class.getResource与Class.getClassLoader().getResource两种方式读取资源文件
  19. 获得assets文件夹中文件内容
  20. Idea改项目名

热门文章

  1. Wireshark(四):网络性能排查之TCP重传与重复ACK
  2. 从 CPython 源码角度看 Python 垃圾回收机制
  3. [BUUCTF]PWN13——ciscn_2019_n_8
  4. CF1481B New Colony 题解
  5. CF1106A Lunar New Year and Cross Counting 题解
  6. MySQL 定时器
  7. Mysql中不能update自身的解决方法
  8. AcWing1264. 动态求连续区间和 (树状数组做法)
  9. ACwing1212. 地宫取宝
  10. JAVA获取当前请求的URL地址,包含请求链接中的参数