1. Dependency management mechanism of SpringBoot

1.1. Questions

First, when we created a SpringBoot project in the previous section, we imported SpringBoot jar configuration dependencies into the POM file, as shown below: introducing the parent project and supporting web development dependencies

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.6.4</version>
</parent>

<dependencies>
    <! Dependencies to support Web development
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
</dependencies>
Copy the code

Just configure these two dependencies, we all need to use jar package in the development process also do not care about any guide problems, can carry on the project development, what is the reason?

1.2. Parent project does dependency management

The parent project of a Spring Boot project has a parent project. The parent project is used to manage the dependency management of any Spring Boot project. For example, the spring-boot-starter-parent dependency is used as the unified parent dependency management for Spring Boot projects.

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.6.4</version>
</parent>
Copy the code

To delve deeper into why these dependencies are introduced in the Spring Boot project without having to write a version number and what the parent project manages, hold Down CTRL and click spring-boot-starter-parent to access the underlying source file. Spring-boot-starter-parent project spring-boot-dependencies

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-dependencies</artifactId>
    <version>2.6.4</version>
</parent>
Copy the code

< span style = “box-sizing: border-box; color: RGB (74, 74, 74); line-height: 22px; font-size: 14px! Important; word-break: inherit! Important;”

<properties>
    <activemq.version>5.16.4</activemq.version>
    <antlr2.version>2.7.7</antlr2.version>
    <appengine-sdk.version>1.9.95</appengine-sdk.version>
    <artemis.version>2.19.1</artemis.version>
    <aspectj.version>1.9.7</aspectj.version>
    <assertj.version>3.21.0</assertj.version>
    <atomikos.version>4.0.6</atomikos.version>
    <awaitility.version>4.1.1</awaitility.version>
    <build-helper-maven-plugin.version>3.2.0</build-helper-maven-plugin.version>
    <byte-buddy.version>1.11.22</byte-buddy.version>
    <caffeine.version>2.9.3</caffeine.version>
    <cassandra-driver.version>4.13.0</cassandra-driver.version>
    <classmate.version>1.5.1</classmate.version>.Copy the code

< span style = “box-sizing: border-box; color: RGB (74, 74, 74); line-height: 22px; font-size: 14px! Important; word-break: inherit! Important;” And these are all versions supported by our current SpringBoot environment. As follows:

This is why all the following dependency files do not need to be marked with dependency version numbers after pom.xml introduced the parent project. For example, the version constraint of the logback package is

1.2.10
, and this constraint is used for all logback dependencies:

For example, we don’t need to write the version number of the MySQL driver, because the parent project has already been introduced, as follows:

<mysql.version>8.0.28</mysql.version>

<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>${mysql.version}</version>
    <exclusions>
        <exclusion>
            <groupId>com.google.protobuf</groupId>
            <artifactId>protobuf-java</artifactId>
        </exclusion>
    </exclusions>
</dependency>
Copy the code

To introduce mysql coordinates into the project Pom file without writing the version number, as follows

<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
</dependency>
Copy the code

Conclusion:

Through layer upon layer inheritance, Spring Boot version constraints can be implemented for corresponding projects without registering version numbers when referencing commercial dependencies, which is the automatic version arbitration mechanism of Spring Boot. Spring-boot-starter -parent The parent dependent initiator provides unified version management. So many dependencies can be generated in the parent project that if the child project inherits the parent project, the child project does not need the version number to write its dependencies later.

For example, if I want to introduce the logback-access dependency in the POM file, I do not need to write the version number, because the parent project has already configured it for us, and also supports the version number in this environment.

1.3. Introduce non-version-mediated jars

From the above statement, we can see that our Mysql dependency is introduced in the corresponding parent project setting is version 8

However, the client we installed is version 5.7 [driven by 5.1], so we have to change the version constraints configured in the parent project. In other words, if you need to modify the version constraint of automatic version arbitration, you can declare properties in the POM file and import the required version number:

  • To view spring-boot-dependencies Which specifies the version of the current dependency.
  • Search the Maven repository to find a satisfactory driver. Maven Repository: Central (mvnrepository.com)
  • If the version number we want is not the same as the auto-quorum version number, we can change the driver. In the pom.xml file, overrideproperties
  • If the imported version number is5.1.43MySQL driver; MySQL driver; MySQL driver;
<! -- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>5.1.43</version>
</dependency>
Copy the code

Declare it as follows: use the

attribute

<properties>
    <mysql.version>5.1.43</mysql.version>
</properties>

<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
</dependency>
Copy the code

Then refresh the Maven dependency and check the External Libraries to see that MySQL version has changed to 5.1.43

1.4 scenario Starter relies on initiators

For example, if you are developing a Web application, you don’t need to know which JAR packages to import, just import the spring-Web scenario in the pom.xml file: Spring-boot-starter-web. As soon as we introduce the starter, we automatically introduce all the normal required dependencies for this scenario.

<dependencies>
    <! Dependencies to support Web development
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
</dependencies>
Copy the code

So where do the other JARS that the project runs on come from? Enter the spring-boot-starter-web underlying source file, and the core code is as follows:

<dependencies>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter</artifactId>
      <version>2.6.4</version>
      <scope>compile</scope>
    </dependency>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-json</artifactId>
      <version>2.6.4</version>
      <scope>compile</scope>
    </dependency>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-tomcat</artifactId>
      <version>2.6.4</version>
      <scope>compile</scope>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-web</artifactId>
      <version>5.3.16</version>
      <scope>compile</scope>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-webmvc</artifactId>
      <version>5.3.16</version>
      <scope>compile</scope>
    </dependency>
  </dependencies>
Copy the code

You can also right-click spring-boot-starter-web -> Diagrams -> Show Dependencies to view the analysis dependency tree.

As can be seen, the spring-boot-starter-Web dependency initiator mainly provides all low-level dependencies required by Web development scenarios. So by introducing the spring-boot-starter-web dependent initiator in pum.xml, web scenario development can be achieved without the need to import additional Tomcat server dependencies and other Web dependency files.

However, these imported dependency file versions are managed by spring-boot-starter-parent.

1.5. Develop dependent initiators in the starter scenario

In addition to providing the dependent initiator for web scenarios, Spring Boot also provides dependencies required by many scenarios. Spring-boot-starter -* represents various application scenarios, simplifying development

  • Once the starter is introduced, all the normal dependencies required for the scenario are automatically introduced.
  • SpringBoot all supported scenarios depend on the launcher reference address: docs.spring. IO /spring-boot…

Supplement:

See *-spring-boot-starter: this is a third-party scenario to simplify development for us to rely on the starter, such as: Mybatis -spring-boot-starter, etc.. You can import it directly into the POM.xml file as needed, but you need to manage the version number yourself.

Spring Boot official documentation explains:

  • The starters contain a lot of the dependencies that you need to get a project up and running quickly and with a consistent, supported set of managed transitive dependencies.
  • That means every single one of themstarterAre a set of dependency sets, providing all the dependency sets required for a certain application scenario. The corresponding dependency sets are introduced when learning an application scenario in the primary stagestarterThe introduction of the required dependencies can be implemented. You can also create your own definitions at a later stagestarter, but the custom name is*-spring-boot-startersuch

To view the configuration of the Web starter, click spring-boot-starter-web. You can view the following configuration dependencies:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter</artifactId>
    <version>2.6.4</version>
    <scope>compile</scope>
</dependency>
Copy the code

Included in any starter scenario starter, this dependency is the core of Spring’s automatic configuration and the base of all scenario configurators. The lowest level dependency of the starter in all scenarios is spring-boot-starter

1.6 summary of dependency management

  • The parent project does dependency management

  • Developing and importing an initiator in the starter scenario

  • No need to pay attention to the version number, automatic version arbitration

    • Importing dependencies by default can be done without writing versions
    • To introduce a jar that is not versioned, write the version number
  • You can change the default version number

2. Automatic configuration features for SpringBoot

As you can see from the HelloWorld-Web project in the previous section, SpringBoot has configured the following for us:

1. Automatically configure Tomcat

Introducing Tomcat dependencies (the Tomcat scenario is introduced by default when the spring-boot-starter-Web development scenario is introduced);

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-tomcat</artifactId>
    <version>2.6.4</version>
    <scope>compile</scope>
</dependency>
Copy the code

Then the automatic configuration of Tomcat refer to the source code analysis in the following sections

2. Automatically configure SpringMVC

  • The introduction of the full set of components of SpringMVC development (the introduction of spring-boot-starter-Web development scenario, the default introduction of spring-Web, Spring-WebMVC scenario);
  • Automatic configuration of SpringMVC common components (features), such as filters for character encoding issues, DispatcherServlet, ViewResolver view parser, etc.
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-web</artifactId>
    <version>5.3.16</version>
    <scope>compile</scope>
</dependency>
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-webmvc</artifactId>
    <version>5.3.16</version>
    <scope>compile</scope>
</dependency>
Copy the code

3, automatically set common Web functions

SpringBoot has configured all the Web development scenarios for us. Addressed the dispatcherServlet in previous SpringMVC Component, characterEncodingFilter, ViewResolver, multipartResolver configuration

We can start the class through the following program to get view

@SpringBootApplication
public class MainApplication{
    public static void main(String[] args) {
        1. Return our IOC container
        ConfigurableApplicationContext run = SpringApplication.run(MainApplication.class, args);
        //2. The container contains all the components of our current application,
        // Check the components in the container, as long as there is our component, the component will work, that is the principle
        String[] names = run. getBeanDefinitionNames();// Get the names of all our component definitions;
        for(String name : names) { System.out.println(name); }}}Copy the code

Results:

Also, if we tell the server to return a Chinese string, there will be no error, no Chinese garble

4. Default package structure

We don’t have any package scanning rules configured, but components in the main program package and all subpackages below it are scanned by default. The official instructions are as follows:

com
 +- example
     +- myapplication  // The package where the main program resides
         +- MyApplication.java  // The main program starts the class
         |
         +- customer
         |   +- Customer.java
         |   +- CustomerController.java
         |   +- CustomerService.java
         |   +- CustomerRepository.java
         |
         +- order
             +- Order.java
             +- OrderController.java
             +- OrderService.java
             +- OrderRepository.java
Copy the code

The MyApplication.java file would declare the main method, along with the basic @SpringBootApplication, as follows:

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class MyApplication {

    public static void main(String[] args) { SpringApplication.run(MyApplication.class, args); }}Copy the code

Look at our project structure, that’s it

So no bag scan configuration, the main program in the inside of the bag and the following all child bag components will be the default scanning come in, but if not other programs (such as controller code) and the main program put together, is not the main program in the same package or their child bag bag, in violation of the default package structure, are as follows:

If this is to run successfully:

  • Method 1: Initiate class (main program) modification@SpringBootApplicationThe default configuration of the annotations changes the scan path to enlarge the level of the scanned package, that is:@ SpringBootApplication (scanBasePackages = "com. Atguigu");
@SpringBootApplication(scanBasePackages = "com.atguigu")
public class MyApplication {
    public static void main(String[] args) { SpringApplication.run(MyApplication.class, args); }}Copy the code
  • Method 2: Start class (main program) use@ComponentScanPacket scan to specify the scan path. Due to the@SpringBootApplicationis@SpringBootConfiguration,@EnableAutoConfiguration,@ComponentScanThree annotations combined annotations, so so directly change the inside@ComponentScanScan the path
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan("com.atguigu")
public class MainApplication {
    public static void main(String[ ] args){ SpringApplication.run(MainApplication.class, args); }}Copy the code

5. All configurations have default values

For example, tomcat is the default port 8080, set in application. Properties via server.port, or SpringMVC file upload, Mybatis configuration, For details about the configuration, see docs. Spring-boot…

But idea has automatic prompt function, for example, I want to see what SpringMVC file upload can configure, as follows:

For example: file upload size

#server.port=8080
The default is 1MB
spring.servlet.multipart.max-file-size=10MB
Copy the code

If you go into the configuration source code, you will find that the default configuration is eventually mapped to a class, such as MultipartProperties

@ConfigurationProperties( prefix = "spring.servlet.multipart", ignoreUnknownFields = false )
public class MultipartProperties {
    private boolean enabled = true;
    private String location;
    private DataSize maxFileSize = DataSize.ofMegabytes(1L);
    private DataSize maxRequestSize = DataSize.ofMegabytes(10L);
    private DataSize fileSizeThreshold = DataSize.ofBytes(0L);
    private boolean resolveLazily = false;

    public MultipartProperties(a) {}public boolean getEnabled(a) {
        return this.enabled;
    }
Copy the code

The default configuration eventually maps to a class, such as: MultipartProperties, the value of the configuration file will eventually be bound to a class that creates objects in the container. The value of the object is the value bound to the configuration file. Modify the default values of various configurations in the application. The default configuration takes effect and objects are created in the container.

6. Load all automatic configuration items on demand

SpringBoot introduces a lot of starter, but the automatic configuration of the starter will be enabled only when certain scenarios are introduced. For example, the automatic configuration of the Web is enabled only when web scenarios are introduced. All of SpringBoot’s auto-configuration capabilities are in the Spring-boot-Autoconfigure JAR

To reiterate: not all auto-configuration classes in the auto-configuration package will take effect. The default configuration will only take effect if the corresponding scenario is imported, and objects will be created in the container, such as the batch class in this auto-configuration class: Since we did not import the starter scenario for batch processing, no object will be created in the container, its configuration will not take effect, and the configuration will be useless. This is called loading on demand