Spring Boot的特点(依赖管理和自动配置)

1、依赖管理

  Spring Boot的每个版本都提供了一个它所支持的依赖的列表。 在开发中,我们不需要在构建配置中为这些依赖声明版本,因为Spring Boot会帮我们管理这些。 当我们升级Spring Boot本身时,这些依赖也会一同升级。
  它的实现原理就是前面我们讲过spring-boot-starter-parent,它 是一个特殊的starter,它在它的pom.xml 的 dependency-management 里面声明了spring boot的各个依赖及其版本。子项目直接继承它,子项在导入 spring boot 依赖时,就不需要声明版本号。

在这里几乎声明了所有开发中常用的依赖的版本号
<parent>
		<groupId>org.springframework.bootgroupId>
		<artifactId>spring-boot-starter-parentartifactId>
		<version>3.0.0version>
		<relativePath/> 
parent>

下面是spring-boot-starter-parent声明的版本号信息

 <properties>
    <angus-mail.version>1.0.0angus-mail.version>
    <artemis.version>2.26.0artemis.version>
    <aspectj.version>1.9.9.1aspectj.version>
    <assertj.version>3.23.1assertj.version>
    <awaitility.version>4.2.0awaitility.version>
    <brave.version>5.14.1brave.version>
    <build-helper-maven-plugin.version>3.3.0build-helper-maven-plugin.version>
    <byte-buddy.version>1.12.19byte-buddy.version>
    <cache2k.version>2.6.1.Finalcache2k.version>
    <caffeine.version>3.1.2caffeine.version>
    <cassandra-driver.version>4.15.0cassandra-driver.version>
    <classmate.version>1.5.1classmate.version>
    <commons-codec.version>1.15commons-codec.version>
    <commons-dbcp2.version>2.9.0commons-dbcp2.version>
    <commons-lang3.version>3.12.0commons-lang3.version>
    <commons-pool.version>1.6commons-pool.version>
    <commons-pool2.version>2.11.1commons-pool2.version>
    <couchbase-client.version>3.4.0couchbase-client.version>
    <db2-jdbc.version>11.5.8.0db2-jdbc.version>
    <dependency-management-plugin.version>1.1.0dependency-management-plugin.version>
    <derby.version>10.16.1.1derby.version>
    <dropwizard-metrics.version>4.2.13dropwizard-metrics.version>
    <ehcache3.version>3.10.8ehcache3.version>
    <elasticsearch-client.version>8.5.1elasticsearch-client.version>
    <flyway.version>9.5.1flyway.version>
    <freemarker.version>2.3.31freemarker.version>
    <git-commit-id-plugin.version>5.0.0git-commit-id-plugin.version>
    <glassfish-jaxb.version>4.0.1glassfish-jaxb.version>
    <glassfish-jstl.version>3.0.1glassfish-jstl.version>
    <graphql-java.version>19.2graphql-java.version>
    <groovy.version>4.0.6groovy.version>
    <gson.version>2.9.1gson.version>
    <h2.version>2.1.214h2.version>
    <hamcrest.version>2.2hamcrest.version>
    <hazelcast.version>5.1.5hazelcast.version>
    <hibernate.version>6.1.5.Finalhibernate.version>
    <hibernate-validator.version>8.0.0.Finalhibernate-validator.version>
    <hikaricp.version>5.0.1hikaricp.version>
    <hsqldb.version>2.7.1hsqldb.version>
    <htmlunit.version>2.65.1htmlunit.version>
    <httpasyncclient.version>4.1.5httpasyncclient.version>
    <httpclient.version>4.5.13httpclient.version>
    <httpclient5.version>5.1.4httpclient5.version>
    <httpcore.version>4.4.15httpcore.version>
    <httpcore5.version>5.1.5httpcore5.version>
    <infinispan.version>14.0.2.Finalinfinispan.version>
    <influxdb-java.version>2.23influxdb-java.version>
    <jackson-bom.version>2.14.1jackson-bom.version>
    <jakarta-activation.version>2.1.0jakarta-activation.version>
    <jakarta-annotation.version>2.1.1jakarta-annotation.version>
    <jakarta-jms.version>3.1.0jakarta-jms.version>
    <jakarta-json.version>2.1.1jakarta-json.version>
    <jakarta-json-bind.version>3.0.0jakarta-json-bind.version>
    <jakarta-mail.version>2.1.0jakarta-mail.version>
    <jakarta-management.version>1.1.4jakarta-management.version>
    <jakarta-persistence.version>3.1.0jakarta-persistence.version>
    <jakarta-servlet.version>6.0.0jakarta-servlet.version>
    <jakarta-servlet-jsp-jstl.version>3.0.0jakarta-servlet-jsp-jstl.version>
    <jakarta-transaction.version>2.0.1jakarta-transaction.version>
    <jakarta-validation.version>3.0.2jakarta-validation.version>
    <jakarta-websocket.version>2.1.0jakarta-websocket.version>
    <jakarta-ws-rs.version>3.1.0jakarta-ws-rs.version>
    <jakarta-xml-bind.version>4.0.0jakarta-xml-bind.version>
    <jakarta-xml-soap.version>3.0.0jakarta-xml-soap.version>
    <jakarta-xml-ws.version>4.0.0jakarta-xml-ws.version>
    <janino.version>3.1.9janino.version>
    <javax-cache.version>1.1.1javax-cache.version>
    <javax-money.version>1.1javax-money.version>
    <jaxen.version>1.2.0jaxen.version>
    <jaybird.version>4.0.7.java11jaybird.version>
    <jboss-logging.version>3.5.0.Finaljboss-logging.version>
    <jdom2.version>2.0.6.1jdom2.version>
    <jedis.version>4.3.1jedis.version>
    <jersey.version>3.1.0jersey.version>
    <jetty-reactive-httpclient.version>3.0.7jetty-reactive-httpclient.version>
    <jetty.version>11.0.12jetty.version>
    <jmustache.version>1.15jmustache.version>
    <jooq.version>3.17.5jooq.version>
    <json-path.version>2.7.0json-path.version>
    <json-smart.version>2.4.8json-smart.version>
    <jsonassert.version>1.5.1jsonassert.version>
    <jtds.version>1.3.1jtds.version>
    <junit.version>4.13.2junit.version>
    <junit-jupiter.version>5.9.1junit-jupiter.version>
    <kafka.version>3.3.1kafka.version>
    <kotlin.version>1.7.21kotlin.version>
    <kotlin-coroutines.version>1.6.4kotlin-coroutines.version>
    <lettuce.version>6.2.1.RELEASElettuce.version>
    <liquibase.version>4.17.2liquibase.version>
    <log4j2.version>2.19.0log4j2.version>
    <logback.version>1.4.5logback.version>
    <lombok.version>1.18.24lombok.version>
    <mariadb.version>3.0.9mariadb.version>
    <maven-antrun-plugin.version>3.1.0maven-antrun-plugin.version>
    <maven-assembly-plugin.version>3.4.2maven-assembly-plugin.version>
    <maven-clean-plugin.version>3.2.0maven-clean-plugin.version>
    <maven-compiler-plugin.version>3.10.1maven-compiler-plugin.version>
    <maven-dependency-plugin.version>3.3.0maven-dependency-plugin.version>
    <maven-deploy-plugin.version>3.0.0maven-deploy-plugin.version>
    <maven-enforcer-plugin.version>3.1.0maven-enforcer-plugin.version>
    <maven-failsafe-plugin.version>2.22.2maven-failsafe-plugin.version>
    <maven-help-plugin.version>3.3.0maven-help-plugin.version>
    <maven-install-plugin.version>3.0.1maven-install-plugin.version>
    <maven-invoker-plugin.version>3.3.0maven-invoker-plugin.version>
    <maven-jar-plugin.version>3.3.0maven-jar-plugin.version>
    <maven-javadoc-plugin.version>3.4.1maven-javadoc-plugin.version>
    <maven-resources-plugin.version>3.3.0maven-resources-plugin.version>
    <maven-shade-plugin.version>3.4.1maven-shade-plugin.version>
    <maven-source-plugin.version>3.2.1maven-source-plugin.version>
    <maven-surefire-plugin.version>2.22.2maven-surefire-plugin.version>
    <maven-war-plugin.version>3.3.2maven-war-plugin.version>
    <micrometer.version>1.10.2micrometer.version>
    <micrometer-tracing.version>1.0.0micrometer-tracing.version>
    <mockito.version>4.8.1mockito.version>
    <mongodb.version>4.8.0mongodb.version>
    <mssql-jdbc.version>11.2.1.jre17mssql-jdbc.version>
    <mysql.version>8.0.31mysql.version>
    <native-build-tools-plugin.version>0.9.18native-build-tools-plugin.version>
    <nekohtml.version>1.9.22nekohtml.version>
    <neo4j-java-driver.version>5.2.0neo4j-java-driver.version>
    <netty.version>4.1.85.Finalnetty.version>
    <okhttp.version>4.10.0okhttp.version>
    <opentelemetry.version>1.19.0opentelemetry.version>
    <oracle-database.version>21.7.0.0oracle-database.version>
    <oracle-r2dbc.version>1.0.0oracle-r2dbc.version>
    <pooled-jms.version>3.0.0pooled-jms.version>
    <postgresql.version>42.5.1postgresql.version>
    <prometheus-client.version>0.16.0prometheus-client.version>
    <quartz.version>2.3.2quartz.version>
    <querydsl.version>5.0.0querydsl.version>
    <r2dbc-h2.version>1.0.0.RELEASEr2dbc-h2.version>
    <r2dbc-pool.version>1.0.0.RELEASEr2dbc-pool.version>
    <r2dbc-postgresql.version>1.0.0.RELEASEr2dbc-postgresql.version>
    <r2dbc-proxy.version>1.0.1.RELEASEr2dbc-proxy.version>
    <r2dbc-spi.version>1.0.0.RELEASEr2dbc-spi.version>
    <rabbit-amqp-client.version>5.16.0rabbit-amqp-client.version>
    <rabbit-stream-client.version>0.8.0rabbit-stream-client.version>
    <reactive-streams.version>1.0.4reactive-streams.version>
    <reactor-bom.version>2022.0.0reactor-bom.version>
    <rest-assured.version>5.2.1rest-assured.version>
    <rsocket.version>1.1.3rsocket.version>
    <rxjava3.version>3.1.5rxjava3.version>
    <saaj-impl.version>3.0.0saaj-impl.version>
    <selenium.version>4.5.3selenium.version>
    <selenium-htmlunit.version>4.5.2selenium-htmlunit.version>
    <sendgrid.version>4.9.3sendgrid.version>
    <slf4j.version>2.0.4slf4j.version>
    <snakeyaml.version>1.33snakeyaml.version>
    <spring-amqp.version>3.0.0spring-amqp.version>
    <spring-batch.version>5.0.0spring-batch.version>
    <spring-data-bom.version>2022.0.0spring-data-bom.version>
    <spring-framework.version>6.0.2spring-framework.version>
    <spring-graphql.version>1.1.0spring-graphql.version>
    <spring-hateoas.version>2.0.0spring-hateoas.version>
    <spring-integration.version>6.0.0spring-integration.version>
    <spring-kafka.version>3.0.0spring-kafka.version>
    <spring-ldap.version>3.0.0spring-ldap.version>
    <spring-restdocs.version>3.0.0spring-restdocs.version>
    <spring-retry.version>2.0.0spring-retry.version>
    <spring-security.version>6.0.0spring-security.version>
    <spring-session.version>3.0.0spring-session.version>
    <spring-ws.version>4.0.0spring-ws.version>
    <sqlite-jdbc.version>3.39.4.1sqlite-jdbc.version>
    <thymeleaf.version>3.1.0.RELEASEthymeleaf.version>
    <thymeleaf-extras-data-attribute.version>2.0.1thymeleaf-extras-data-attribute.version>
    <thymeleaf-extras-springsecurity.version>3.1.0.RELEASEthymeleaf-extras-springsecurity.version>
    <thymeleaf-layout-dialect.version>3.1.0thymeleaf-layout-dialect.version>
    <tomcat.version>10.1.1tomcat.version>
    <unboundid-ldapsdk.version>6.0.6unboundid-ldapsdk.version>
    <undertow.version>2.3.0.Finalundertow.version>
    <versions-maven-plugin.version>2.12.0versions-maven-plugin.version>
    <webjars-locator-core.version>0.52webjars-locator-core.version>
    <wsdl4j.version>1.6.3wsdl4j.version>
    <xml-maven-plugin.version>1.0.2xml-maven-plugin.version>
    <xmlunit2.version>2.9.0xmlunit2.version>
    <yasson.version>3.0.2yasson.version>
  properties>

  虽然spring boot为我们提供了版本号,但是我们仍然可以指定某个依赖的版本,来覆盖spring boot默认的版本。它的原理是maven的自动仲裁机制会优先使用子项目定义的版本号。所以我们只要在子项目的pom中定义版本号,默认的版本号就不会生效了。 如下例所示:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>3.0.0</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>
	<groupId>com.tellhow</groupId>
	<artifactId>springbootstudy3.0</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>springbootstudy3.0</name>
	<description>Demo project for Spring Boot</description>
	<properties>
		<mysql.version>8.0.11</mysql.version>
	</properties>
</project>

  SpringBoot给我们提供的mysql的版本是8.0.31,但是我们在子项目中重新定义了版本号为8.0.11。由于Maven的版本仲裁机制是优先使用子项的,所以项目中mysql实际导入的版本是8.0.11。
虽然可以重新定义版本号,但是Spring Boot的每个版本都与Spring框架的基本版本有关。 所以Spring Boot官网强烈建议不要修改它默认的版本

2、启动器(Starter)

  Starter是一系列开箱即用的依赖,你可以在你的应用程序中导入它们。 通过你Starter,可以获得所有你需要的Spring和相关技术的一站式服务,免去了需要到处大量复制粘贴依赖的烦恼。 例如,如果你想开始使用Spring和JPA进行数据库访问,那么可以直接在你的项目中导入 spring-boot-starter-data-jpa 依赖。
  Starter包含了很多项目开发需要的依赖,以使项目快速启动和运行,并拥有一套一致的、受支持的可管理的过渡性依赖。
关于Starter的命名:
  所有官方的Starter都遵循一个类似的命名模式;spring-boot-starter-*,其中 * 是一个特定类型的应用程序。 这种命名结构是为了在你需要寻找Starter时提供帮助。 许多IDE中集成的Maven可以让你按名称搜索依赖。 例如,如果安装了相应的Eclipse或Spring Tools插件,你可以在POM编辑器中按下 ctrl-space ,然后输入 “spring-boot-starter” 来获取完整的列表。
  第三方启动器不应该以 spring-boot 开头,因为它是留给Spring Boot官方组件的。 相反,第三方启动器通常以项目的名称开始。 例如,一个名为 thirdpartyproject 的第三方启动器项目通常被命名为 thirdpartyproject-spring-boot-starter。
  以下是Spring Boot在给我们提供的starter组件。

Name 	                         Description

spring-boot-starter                           Core starter, including auto-configuration support, logging and YAML
 
spring-boot-starter-amqp                      Starter for using Spring AMQP and Rabbit MQ

spring-boot-starter-aop                       Starter for aspect-oriented programming with Spring AOP and AspectJ

spring-boot-starter-artemis                   Starter for JMS messaging using Apache Artemis

spring-boot-starter-batch                     Starter for using Spring Batch

spring-boot-starter-cache                     Starter for using Spring Framework’s caching support

spring-boot-starter-data-cassandra            Starter for using Cassandra distributed database and Spring Data Cassandra

spring-boot-starter-data-cassandra-reactive   Starter for using Cassandra distributed database and Spring Data Cassandra Reactive

spring-boot-starter-data-couchbase            Starter for using Couchbase document-oriented database and Spring Data Couchbase

spring-boot-starter-data-couchbase-reactive   Starter for using Couchbase document-oriented database and Spring Data Couchbase Reactive

spring-boot-starter-data-elasticsearch        Starter for using Elasticsearch search and analytics engine and Spring Data Elasticsearch

spring-boot-starter-data-jdbc                 Starter for using Spring Data JDBC

spring-boot-starter-data-jpa                  Starter for using Spring Data JPA with Hibernate

spring-boot-starter-data-ldap                 Starter for using Spring Data LDAP

spring-boot-starter-data-mongodb              Starter for using MongoDB document-oriented database and Spring Data MongoDB                                 
spring-boot-starter-data-mongodb-reactive     Starter for using MongoDB document-oriented database and Spring Data MongoDB Reactive

spring-boot-starter-data-neo4j                Starter for using Neo4j graph database and Spring Data Neo4j

spring-boot-starter-data-r2dbc                Starter for using Spring Data R2DBC

spring-boot-starter-data-redis                Starter for using Redis key-value data store with Spring Data Redis and the Lettuce client

spring-boot-starter-data-redis-reactive       Starter for using Redis key-value data store with Spring Data Redis reactive and the Lettuce client

spring-boot-starter-data-rest                 Starter for exposing Spring Data repositories over REST using Spring Data REST

spring-boot-starter-freemarker                Starter for building MVC web applications using FreeMarker views

spring-boot-starter-graphql                   Starter for building GraphQL applications with Spring GraphQL

spring-boot-starter-groovy-templates          Starter for building MVC web applications using Groovy Templates views

spring-boot-starter-hateoas                   Starter for building hypermedia-based RESTful web application with Spring MVC and Spring HATEOAS

spring-boot-starter-integration                   Starter for using Spring Integration

spring-boot-starter-jdbc                          Starter for using JDBC with the HikariCP connection pool       
spring-boot-starter-jersey                        Starter for building RESTful web applications using JAX-RS and Jersey. An alternative to spring-boot-starter-web

spring-boot-starter-jooq                         Starter for using jOOQ to access SQL databases with JDBC. An alternative to spring-boot-starter-data-jpa or spring-boot-starter-jdbc

spring-boot-starter-json                         Starter for reading and writing json

spring-boot-starter-mail                         Starter for using Java Mail and Spring Framework’s email sending support

spring-boot-starter-mustache                     Starter for building web applications using Mustache views

spring-boot-starter-oauth2-client                Starter for using Spring Security’s OAuth2/OpenID Connect client features

spring-boot-starter-oauth2-resource-server       Starter for using Spring Security’s OAuth2 resource server features

spring-boot-starter-quartz             Starter for using the Quartz scheduler

spring-boot-starter-rsocket            Starter for building RSocket clients and servers

spring-boot-starter-security           Starter for using Spring Security

spring-boot-starter-test               Starter for testing Spring Boot applications with libraries including JUnit Jupiter, Hamcrest and Mockito

spring-boot-starter-thymeleaf          Starter for building MVC web applications using Thymeleaf views

spring-boot-starter-validation         Starter for using Java Bean Validation with Hibernate Validator

spring-boot-starter-web                Starter for building web, including RESTful, applications using Spring MVC. Uses Tomcat as the default embedded container

spring-boot-starter-web-services       Starter for using Spring Web Services

spring-boot-starter-webflux            Starter for building WebFlux applications using Spring Framework’s Reactive Web support

spring-boot-starter-websocket          Starter for building WebSocket applications using Spring Framework’s WebSocket support

3. 代码结构

Spring Boot对代码的布局,没有特别的要求。 但是,有一些最佳实践。

3.1.默认的包

  当一个类不包括 package 的声明时,它被认为是在 “default package” 中【即我们创建一个类,没有把它放在包中,它会被认为放在default包下】。 通常应避免使 “default package”。 对于使用了 @ComponentScan, @ConfigurationPropertiesScan, @EntityScan 或者 @SpringBootApplication 注解的Spring Boot应用程序来说,它可能会造成一个问题:项目中的所有jar里面的所有class都会被读取(扫描)。建议将每个类都放在包里面,包名遵循Java推荐的包的命名惯例,使用域名反转作为包名。

3.2. 启动类的位置(默认的包扫描路径)

  通常建议将启动类放在一个根package中,高于其他的类,@SpringBootApplication 注解一般都是注解在启动类上的。它默认会扫描当前类下的所有子包。例如,如果你正在编写一个JPA应用程序,你的 @Entity 类只有定义在启动类的子包下才能被扫描加载到。这样的好处也显而易见,@SpringBootApplication 默认只会扫描加载你项目工程中的组件。

4. 自动配置原理入门

  Spring Boot的自动装配机制会试图根据你所添加的依赖来自动配置你的Spring应用程序。 例如,如果我们添加了spring-boot-starter-web 依赖,那么Spring Boot就会对web功能进行自动配置。我们只需要将 @EnableAutoConfiguration 或 @SpringBootApplication 注解添加到你的 @Configuration 类【配置类】中,就可以开启自动配置功能。接下来我们来研究它是怎么实现自动配置的。

4.1、引导加载自动配置类

  @SpringBootApplication是一个复合注解,它主要由下图中这些注解组成。我们来分别看一下它的作用。
Spring Boot的特点(依赖管理和自动配置)_第1张图片

4.1.1、@SpringBootConfiguration

  @SpringBootConfiguration它本质上就是一个@Configuration注解。它的作用是告诉spring被该注解修饰的类为配置类。

4.1.2、@EnableAutoConfiguration

  @EnableAutoConfiguration也是一个复合注解,它主要由@AutoConfigurationPackage和@Import({AutoConfigurationImportSelector.class})组成,让我们来看它们做了什么。

1)、@AutoConfigurationPackage注解

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

  从上面源码我们可以看到@AutoConfigurationPackage 就是在利用@Import注解给容器导入组件。

Registrar类的关系图。
Spring Boot的特点(依赖管理和自动配置)_第2张图片

  Registrar是ImportBeanDefinitionRegistrar的子类,使用@Import导入ImportBeanDefinitionRegistrar类型的组件时,它会调用registerBeanDefinitions()方法注册bean的定义信息。通过查看源码可以看到,它给容器注册了一个bean的定义信息【name为主配置所在的包名,类型为BasePackages.class】

	static class Registrar implements ImportBeanDefinitionRegistrar, DeterminableImports {
		@Override
		public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
			register(registry, new PackageImports(metadata).getPackageNames().toArray(new String[0]));
		}
-------------------------------------上面方法调用下面方法-----------------------------------------------------
		public static void register(BeanDefinitionRegistry registry, String... packageNames) {
		if (registry.containsBeanDefinition(BEAN)) {
			addBasePackages(registry.getBeanDefinition(BEAN), packageNames);
		}
		else {
			RootBeanDefinition beanDefinition = new RootBeanDefinition(BasePackages.class);
			beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
			addBasePackages(beanDefinition, packageNames);
			registry.registerBeanDefinition(BEAN, beanDefinition);
		}
	}
}

2)、@Import(AutoConfigurationImportSelector.class)[自动配置类加载到容器]

Spring Boot的特点(依赖管理和自动配置)_第3张图片  通过AutoConfigurationImportSelector的类的关系图我们可以做到,它是ImportSelector的子类。使用@Import注解导入这种类型的组件时,它会调用 selectImports()方法,根据导入的@Configuration类的AnnotationMetadata选择并返回应该导入的类的名称

   @Override
	public String[] selectImports(AnnotationMetadata annotationMetadata) {
		if (!isEnabled(annotationMetadata)) {
			return NO_IMPORTS;
		}
		AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry(annotationMetadata);//获取应该导入的自动配置
		return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
	}

在selectImports通过调用getAutoConfigurationEntry()方法,获取应该导入的自动配置。
  1)调用getCandidateConfigurations()获取候选的配置

protected AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {
		if (!isEnabled(annotationMetadata)) {
			return EMPTY_ENTRY;
		}
		AnnotationAttributes attributes = getAttributes(annotationMetadata);//获取@EnableAutoConfiguration注解的属性
		List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);//返回应该考虑的自动配置类名
		configurations = removeDuplicates(configurations);
		Set<String> exclusions = getExclusions(annotationMetadata, attributes);
		checkExcludedClasses(configurations, exclusions);
		configurations.removeAll(exclusions);
		configurations = getConfigurationClassFilter().filter(configurations);
		fireAutoConfigurationImportEvents(configurations, exclusions);
		return new AutoConfigurationEntry(configurations, exclusions);
	}
-----------------------1.1、返回自动配置类的类名---------------------------------------------
  protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
		List<String> configurations = ImportCandidates.load(AutoConfiguration.class, getBeanClassLoader())
				.getCandidates();
		Assert.notEmpty(configurations,
				"No auto configuration classes found in "
						+ "META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports. If you "
						+ "are using a custom packaging, make sure that file is correct.");
		return configurations;
	}

------------------------1.2、从类路径加载导入候选项的名称------------------------------------------
public static ImportCandidates load(Class<?> annotation, ClassLoader classLoader) {
		Assert.notNull(annotation, "'annotation' must not be null");
		ClassLoader classLoaderToUse = decideClassloader(classLoader);
		//LOCATION = "META-INF/spring/%s.imports";
		//annotation.getName()=org.springframework.boot.autoconfigure.AutoConfiguration
		//1、指定搜索的路径location=META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports 
		String location = String.format(LOCATION, annotation.getName());//指定搜索的路径
		Enumeration<URL> urls = findUrlsInClasspath(classLoaderToUse, location);//2、查找具有给定名称的所有资源,名称为META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports 的资源
		List<String> importCandidates = new ArrayList<>();
		while (urls.hasMoreElements()) {
			URL url = urls.nextElement();
			importCandidates.addAll(readCandidateConfigurations(url));
		}
		return new ImportCandidates(importCandidates);
	}
	----------------1.3、在指定的资源中获取候选的配置readCandidateConfigurations(url)---------------------------------------------
//url=jar:file:/D:/software/application/StudyOrWorkApp/apache-maven-3.6.0/conf/th_repository/org/springframework/boot/spring-boot-autoconfigure/3.0.0/spring-boot-autoconfigure-3.0.0.jar!/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports  -------以这个路径为例
private static List<String> readCandidateConfigurations(URL url) {
		try (BufferedReader reader = new BufferedReader(
				new InputStreamReader(new UrlResource(url).getInputStream(), StandardCharsets.UTF_8))) {
			List<String> candidates = new ArrayList<>();
			String line;
			while ((line = reader.readLine()) != null) {
				line = stripComment(line);
				line = line.trim();
				if (line.isEmpty()) {
					continue;
				}
				candidates.add(line);
			}
			return candidates;
		}
		catch (IOException ex) {
			throw new IllegalArgumentException("Unable to load configurations from location [" + url + "]", ex);
		}
	}

    1.4、进行到这一步,我们看到SpringBoot会去读取我们类路径下,路径为META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports 的文件。我们去看一下这个文件里面有什么。
Spring Boot的特点(依赖管理和自动配置)_第4张图片在META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports 中存放了下面这些信息

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
org.springframework.boot.autoconfigure.dao.PersistenceExceptionTranslationAutoConfiguration
org.springframework.boot.autoconfigure.data.cassandra.CassandraDataAutoConfiguration
org.springframework.boot.autoconfigure.data.cassandra.CassandraReactiveDataAutoConfiguration
org.springframework.boot.autoconfigure.data.cassandra.CassandraReactiveRepositoriesAutoConfiguration
org.springframework.boot.autoconfigure.data.cassandra.CassandraRepositoriesAutoConfiguration
org.springframework.boot.autoconfigure.data.couchbase.CouchbaseDataAutoConfiguration
org.springframework.boot.autoconfigure.data.couchbase.CouchbaseReactiveDataAutoConfiguration
org.springframework.boot.autoconfigure.data.couchbase.CouchbaseReactiveRepositoriesAutoConfiguration
org.springframework.boot.autoconfigure.data.couchbase.CouchbaseRepositoriesAutoConfiguration
org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchDataAutoConfiguration
org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchRepositoriesAutoConfiguration
org.springframework.boot.autoconfigure.data.elasticsearch.ReactiveElasticsearchRepositoriesAutoConfiguration
org.springframework.boot.autoconfigure.data.jdbc.JdbcRepositoriesAutoConfiguration
org.springframework.boot.autoconfigure.data.jpa.JpaRepositoriesAutoConfiguration
org.springframework.boot.autoconfigure.data.ldap.LdapRepositoriesAutoConfiguration
org.springframework.boot.autoconfigure.data.mongo.MongoDataAutoConfiguration
org.springframework.boot.autoconfigure.data.mongo.MongoReactiveDataAutoConfiguration
org.springframework.boot.autoconfigure.data.mongo.MongoReactiveRepositoriesAutoConfiguration
org.springframework.boot.autoconfigure.data.mongo.MongoRepositoriesAutoConfiguration
org.springframework.boot.autoconfigure.data.neo4j.Neo4jDataAutoConfiguration
org.springframework.boot.autoconfigure.data.neo4j.Neo4jReactiveDataAutoConfiguration
org.springframework.boot.autoconfigure.data.neo4j.Neo4jReactiveRepositoriesAutoConfiguration
org.springframework.boot.autoconfigure.data.neo4j.Neo4jRepositoriesAutoConfiguration
org.springframework.boot.autoconfigure.data.r2dbc.R2dbcDataAutoConfiguration
org.springframework.boot.autoconfigure.data.r2dbc.R2dbcRepositoriesAutoConfiguration
org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration
org.springframework.boot.autoconfigure.data.redis.RedisReactiveAutoConfiguration
org.springframework.boot.autoconfigure.data.redis.RedisRepositoriesAutoConfiguration
org.springframework.boot.autoconfigure.data.rest.RepositoryRestMvcAutoConfiguration
org.springframework.boot.autoconfigure.data.web.SpringDataWebAutoConfiguration
org.springframework.boot.autoconfigure.elasticsearch.ElasticsearchClientAutoConfiguration
org.springframework.boot.autoconfigure.elasticsearch.ElasticsearchRestClientAutoConfiguration
org.springframework.boot.autoconfigure.elasticsearch.ReactiveElasticsearchClientAutoConfiguration
org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration
org.springframework.boot.autoconfigure.freemarker.FreeMarkerAutoConfiguration
org.springframework.boot.autoconfigure.graphql.GraphQlAutoConfiguration
org.springframework.boot.autoconfigure.graphql.data.GraphQlReactiveQueryByExampleAutoConfiguration
org.springframework.boot.autoconfigure.graphql.data.GraphQlReactiveQuerydslAutoConfiguration
org.springframework.boot.autoconfigure.graphql.data.GraphQlQueryByExampleAutoConfiguration
org.springframework.boot.autoconfigure.graphql.data.GraphQlQuerydslAutoConfiguration
org.springframework.boot.autoconfigure.graphql.reactive.GraphQlWebFluxAutoConfiguration
org.springframework.boot.autoconfigure.graphql.rsocket.GraphQlRSocketAutoConfiguration
org.springframework.boot.autoconfigure.graphql.rsocket.RSocketGraphQlClientAutoConfiguration
org.springframework.boot.autoconfigure.graphql.security.GraphQlWebFluxSecurityAutoConfiguration
org.springframework.boot.autoconfigure.graphql.security.GraphQlWebMvcSecurityAutoConfiguration
org.springframework.boot.autoconfigure.graphql.servlet.GraphQlWebMvcAutoConfiguration
org.springframework.boot.autoconfigure.groovy.template.GroovyTemplateAutoConfiguration
org.springframework.boot.autoconfigure.gson.GsonAutoConfiguration
org.springframework.boot.autoconfigure.h2.H2ConsoleAutoConfiguration
org.springframework.boot.autoconfigure.hateoas.HypermediaAutoConfiguration
org.springframework.boot.autoconfigure.hazelcast.HazelcastAutoConfiguration
org.springframework.boot.autoconfigure.hazelcast.HazelcastJpaDependencyAutoConfiguration
org.springframework.boot.autoconfigure.http.HttpMessageConvertersAutoConfiguration
org.springframework.boot.autoconfigure.http.codec.CodecsAutoConfiguration
org.springframework.boot.autoconfigure.influx.InfluxDbAutoConfiguration
org.springframework.boot.autoconfigure.info.ProjectInfoAutoConfiguration
org.springframework.boot.autoconfigure.integration.IntegrationAutoConfiguration
org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration
org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration
org.springframework.boot.autoconfigure.jdbc.JdbcTemplateAutoConfiguration
org.springframework.boot.autoconfigure.jdbc.JndiDataSourceAutoConfiguration
org.springframework.boot.autoconfigure.jdbc.XADataSourceAutoConfiguration
org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration
org.springframework.boot.autoconfigure.jersey.JerseyAutoConfiguration
org.springframework.boot.autoconfigure.jms.JmsAutoConfiguration
org.springframework.boot.autoconfigure.jmx.JmxAutoConfiguration
org.springframework.boot.autoconfigure.jms.JndiConnectionFactoryAutoConfiguration
org.springframework.boot.autoconfigure.jms.artemis.ArtemisAutoConfiguration
org.springframework.boot.autoconfigure.jooq.JooqAutoConfiguration
org.springframework.boot.autoconfigure.jsonb.JsonbAutoConfiguration
org.springframework.boot.autoconfigure.kafka.KafkaAutoConfiguration
org.springframework.boot.autoconfigure.availability.ApplicationAvailabilityAutoConfiguration
org.springframework.boot.autoconfigure.ldap.embedded.EmbeddedLdapAutoConfiguration
org.springframework.boot.autoconfigure.ldap.LdapAutoConfiguration
org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfiguration
org.springframework.boot.autoconfigure.mail.MailSenderAutoConfiguration
org.springframework.boot.autoconfigure.mail.MailSenderValidatorAutoConfiguration
org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration
org.springframework.boot.autoconfigure.mongo.MongoReactiveAutoConfiguration
org.springframework.boot.autoconfigure.mustache.MustacheAutoConfiguration
org.springframework.boot.autoconfigure.neo4j.Neo4jAutoConfiguration
org.springframework.boot.autoconfigure.netty.NettyAutoConfiguration
org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration
org.springframework.boot.autoconfigure.quartz.QuartzAutoConfiguration
org.springframework.boot.autoconfigure.r2dbc.R2dbcAutoConfiguration
org.springframework.boot.autoconfigure.r2dbc.R2dbcTransactionManagerAutoConfiguration
org.springframework.boot.autoconfigure.rsocket.RSocketMessagingAutoConfiguration
org.springframework.boot.autoconfigure.rsocket.RSocketRequesterAutoConfiguration
org.springframework.boot.autoconfigure.rsocket.RSocketServerAutoConfiguration
org.springframework.boot.autoconfigure.rsocket.RSocketStrategiesAutoConfiguration
org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration
org.springframework.boot.autoconfigure.security.servlet.UserDetailsServiceAutoConfiguration
org.springframework.boot.autoconfigure.security.servlet.SecurityFilterAutoConfiguration
org.springframework.boot.autoconfigure.security.reactive.ReactiveSecurityAutoConfiguration
org.springframework.boot.autoconfigure.security.reactive.ReactiveUserDetailsServiceAutoConfiguration
org.springframework.boot.autoconfigure.security.rsocket.RSocketSecurityAutoConfiguration
org.springframework.boot.autoconfigure.security.saml2.Saml2RelyingPartyAutoConfiguration
org.springframework.boot.autoconfigure.sendgrid.SendGridAutoConfiguration
org.springframework.boot.autoconfigure.session.SessionAutoConfiguration
org.springframework.boot.autoconfigure.security.oauth2.client.servlet.OAuth2ClientAutoConfiguration
org.springframework.boot.autoconfigure.security.oauth2.client.reactive.ReactiveOAuth2ClientAutoConfiguration
org.springframework.boot.autoconfigure.security.oauth2.resource.servlet.OAuth2ResourceServerAutoConfiguration
org.springframework.boot.autoconfigure.security.oauth2.resource.reactive.ReactiveOAuth2ResourceServerAutoConfiguration
org.springframework.boot.autoconfigure.sql.init.SqlInitializationAutoConfiguration
org.springframework.boot.autoconfigure.task.TaskExecutionAutoConfiguration
org.springframework.boot.autoconfigure.task.TaskSchedulingAutoConfiguration
org.springframework.boot.autoconfigure.thymeleaf.ThymeleafAutoConfiguration
org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration
org.springframework.boot.autoconfigure.transaction.jta.JtaAutoConfiguration
org.springframework.boot.autoconfigure.validation.ValidationAutoConfiguration
org.springframework.boot.autoconfigure.web.client.RestTemplateAutoConfiguration
org.springframework.boot.autoconfigure.web.embedded.EmbeddedWebServerFactoryCustomizerAutoConfiguration
org.springframework.boot.autoconfigure.web.reactive.HttpHandlerAutoConfiguration
org.springframework.boot.autoconfigure.web.reactive.ReactiveMultipartAutoConfiguration
org.springframework.boot.autoconfigure.web.reactive.ReactiveWebServerFactoryAutoConfiguration
org.springframework.boot.autoconfigure.web.reactive.WebFluxAutoConfiguration
org.springframework.boot.autoconfigure.web.reactive.WebSessionIdResolverAutoConfiguration
org.springframework.boot.autoconfigure.web.reactive.error.ErrorWebFluxAutoConfiguration
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
org.springframework.boot.autoconfigure.websocket.reactive.WebSocketReactiveAutoConfiguration
org.springframework.boot.autoconfigure.websocket.servlet.WebSocketServletAutoConfiguration
org.springframework.boot.autoconfigure.websocket.servlet.WebSocketMessagingAutoConfiguration
org.springframework.boot.autoconfigure.webservices.WebServicesAutoConfiguration
org.springframework.boot.autoconfigure.webservices.client.WebServiceTemplateAutoConfiguration

获取到这些自动配置类的信息。
Spring Boot的特点(依赖管理和自动配置)_第5张图片

4.2、按需开启自动配置项

虽然我们142个场景的所有自动配置启动的时候默认全部加载。xxxxAutoConfiguration
按照条件装配规则(@Conditional),最终会按需配置。

  获取到候选的自动配置类以后,通过过滤器过滤掉不需要的自动配置,调用的是getConfigurationClassFilter().filter(configurations)方法。【条件装配的条件】
Spring Boot的特点(依赖管理和自动配置)_第6张图片然后将过滤后的所有自动装配类的名称集合作为返回值返回【这些类会被加载到容器中】,原理请查看@Import的使用。

4.3、取代自动配置类注册的组件

  我们在给spring注册自动配置类时,自动配置类也会在spring容器中注册许多组件,以WebMvcAutoConfiguration为例。
Spring Boot的特点(依赖管理和自动配置)_第7张图片  我们查看源码发现WebMvcAutoConfiguration自动配置类会在容器中注入OrderedHiddenHttpMethodFilter组件,并且加到容器中要满足一个装配条件【容器中不存在HiddenHttpMethodFilter类型的组件】,所以我们给容器中注入OrderedHiddenHttpMethodFilter类型的组件时。自动配置的OrderedHiddenHttpMethodFilter组件就不会加到容器中去。
  SpringBoot默认会在底层配好所有的组件。但是如果用户自己配置了以用户的优先。
  如果你想知道在应用中使用了哪些自动配置,你可以在配置文件设置debug=true。 这个参数会为核心的logger开启debug级别的日志,会在控制台输出自动装配项目以及触发自动装配的条件。

4.4、禁用指定的自动装配类

如果你想禁用掉项目中某些自动装配类,你可以在使用@SpringBootApplication 注解的 exclude 属性中指定。例如:

import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
@SpringBootApplication(exclude = { DataSourceAutoConfiguration.class })
public class MyApplication {

}

如果要禁用的自动装配类不在classpath上(没有导入),那么你可以在注解的 excludeName 属性中指定类的全路径名称。 exclude 和 excludeName 属性在 @EnableAutoConfiguration 注解中也可以使用。 最后,你也可以在配置文件中通过 spring.autoconfigure.exclude[] 配置来定义要禁用的自动配置类列表
总结:

  1. SpringBoot先加载所有的自动配置类 xxxxxAutoConfiguration
  2. 每个自动配置类按照条件进行生效,默认都会绑定配置文件指定的值。从xxxxProperties里面获取。xxxProperties和配置文件进行了绑定
  3. 生效的配置类就会给容器中装配很多组件
  4. 只要容器中有这些组件,相当于这些功能就有了

你可能感兴趣的:(SpringBoot学习,spring,boot,java,spring)