1. Simplified principle dependent analysis
1.1 spring-boot-starter-parent
Click springboot-starter-parent pom.xml file, jump to the pom.xml springboot-starter-parent's, xml configuration is as follows (here only partially cut key configuration)
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-dependencies</artifactId> <version>2.2.1.RELEASE</version> <relativePath>../../spring-boot-dependencies</relativePath> </parent>
Click spring-boot-starter-dependencies pom.xml the jump to the pom.xml spring-boot-starter-dependencies of the following configuration (some important configuration):
<properties> <activemq.version>5.15.10</activemq.version> <antlr2.version>2.7.7</antlr2.version> <appengine-sdk.version>1.9.76</appengine-sdk.version> <artemis.version>2.10.1</artemis.version> <aspectj.version>1.9.4</aspectj.version> <assertj.version>3.13.2</assertj.version> <atomikos.version>4.0.6</atomikos.version> <awaitility.version>4.0.1</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.2</byte-buddy.version> <caffeine.version>2.8.0</caffeine.version> <cassandra-driver.version>3.7.2</cassandra-driver.version> <classmate.version>1.5.1</classmate.version> <commons-codec.version>1.13</commons-codec.version> .................... </properties> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot</artifactId> <version>2.2.1.RELEASE</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-test</artifactId> <version>2.2.1.RELEASE</version> </dependency> .................... </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> .................... </plugins> </pluginManagement> </build>
We can see from the above pom.xml springboot-starter-dependencies, the version part of coordinates, dependency management, plug-in has been defined, so our engineering springboot succession after springboot-starter-parent already has a version of the lockout configuration a. So start dependent role is passed dependent.
1.2 spring-boot-starter-web
Click spring-boot-starter-web pom.xml the jump to the spring-boot-starter-web of the pom.xml, configured as follows:
<?xml version="1.0" encoding="UTF-8"?> <project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starters</artifactId> <version>2.2.1.RELEASE</version> </parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <version>2.2.1.RELEASE</version> <name>Spring Boot Web Starter</name> <description>Starter for building web, including RESTful, applications using Spring MVC. Uses Tomcat as the default embedded container</description> <url>https://projects.spring.io/spring-boot/#/spring-boot-parent/spring-boot-starters/spring-boot-starter-web</url> <organization> <name>Pivotal Software, Inc.</name> <url>https://spring.io</url> </organization> <licenses> <license> <name>Apache License, Version 2.0</name> <url>https://www.apache.org/licenses/LICENSE-2.0</url> </license> </licenses> <developers> <developer> <name>Pivotal</name> <email>[email protected]</email> <organization>Pivotal Software, Inc.</organization> <organizationUrl>https://www.spring.io</organizationUrl> </developer> </developers> <scm> <connection>scm:git:git://github.com/spring-projects/spring-boot.git</connection> <developerConnection>scm:git:ssh://[email protected]/spring-projects/spring-boot.git</developerConnection> <url>https://github.com/spring-projects/spring-boot</url> </scm> <issueManagement> <system>Github</system> <url>https://github.com/spring-projects/spring-boot/issues</url> </issueManagement> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> <version>2.2.1.RELEASE</version> <scope>compile</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-json</artifactId> <version>2.2.1.RELEASE</version> <scope>compile</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-tomcat</artifactId> <version>2.2.1.RELEASE</version> <scope>compile</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-validation</artifactId> <version>2.2.1.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.1.RELEASE</version> <scope>compile</scope> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>5.2.1.RELEASE</version> <scope>compile</scope> </dependency> </dependencies> </project>
We can see from the spring-boot-starter-web of the pom.xml, spring-boot-starter-web web development is to be used spring-web, spring-webmvc and other coordinates a "package." Such projects as long as we rely on the spring-boot-starter-web, web development can be carried out, also reflects the transitive dependencies role.
2. The principle of automatic configuration parsing
Click @SpringBootApplication notes on startup class, @ SpringBootApplication annotated source code as follows (in part):
@Target (ElementType.TYPE {}) @Retention (RetentionPolicy.RUNTIME) @Documented @Inherited @SpringBootConfiguration // equivalent @Configuration, i.e., labeling of such a configuration is based Spring @EnableAutoConfiguration // SpringBoot automatic configuration turned @ComponentScan ( excludeFilters @Filter = {( type = FilterType.CUSTOM, classes TypeExcludeFilter.class = {} ), @Filter ( type = FilterType.CUSTOM, classes AutoConfigurationExcludeFilter.class = {} )} ) public @interface SpringBootApplication { @AliasFor ( Annotation EnableAutoConfiguration.class = ) Class <? > [] the exclude () {} default; ... ... ... }
Click to view comment @EnableAutoConfiguration
@Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited @AutoConfigurationPackage @Import({AutoConfigurationImportSelector.class}) public @interface EnableAutoConfiguration { String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration"; Class<?>[] exclude() default {}; String[] excludeName() default {}; }
Which, @ Import (AutoConfigurationImportSelector.class) introduced AutoConfigurationImportSelector category, click View source code AutoConfigurationImportSelector
public String[] selectImports(AnnotationMetadata annotationMetadata) { if (!this.isEnabled(annotationMetadata)) { return NO_IMPORTS; } else { AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader.loadMetadata(this.beanClassLoader); AutoConfigurationImportSelector.AutoConfigurationEntry autoConfigurationEntry = this.getAutoConfigurationEntry(autoConfigurationMetadata, annotationMetadata); return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations()); } } ... ... ... protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) { List<String> configurations = SpringFactoriesLoader.loadFactoryNames(this.getSpringFactoriesLoaderFactoryClass(), this.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; }
Wherein the method is to effect SpringFactoriesLoader.loadFactoryNames loading META-INF / spring.factories, this external file has many classes automatically configured.
spring.properties configuration information file on the automatic configuration as follows (only a portion taken for explaining):
There are a lot of class name Configuration ending above configuration file, there are these type of automatic configuration information. SpringApplication get these loaded the class name before.
ServletWebServerFactoryAutoConfiguration an example to analyze:
@Configuration( proxyBeanMethods = false ) @AutoConfigureOrder(-2147483648) @ConditionalOnClass({ServletRequest.class}) @ConditionalOnWebApplication( type = Type.SERVLET ) @EnableConfigurationProperties({ServerProperties.class}) // 加载ServerProperties服务器配置属性类 @Import({ServletWebServerFactoryAutoConfiguration.BeanPostProcessorsRegistrar.class, EmbeddedTomcat.class, EmbeddedJetty.class, EmbeddedUndertow.class}) public class ServletWebServerFactoryAutoConfiguration { ... ... ... }
ServerProperties.class into the source code as follows:
@ConfigurationProperties( prefix = "server", ignoreUnknownFields = true ) public class ServerProperties { private Integer port; private InetAddress address; ... ... ... }
prefix = "server" denotes SpringBoot profile prefix, SpringBoot the configuration file to the server is mapped to the beginning of the attributes of the class field. Mapping relationship as follows: