Casually to the recent want to gradually organize the article named a leathery shrimp: SpringBoot takeoff road
This is the second part of an introduction to some of the basic principles covered in the previous part
Interested friends can go to know about the other several articles have been published, your praise is the biggest support for me, thank you!
- The article directories
SpringBoot takeoff road -HelloWorld
(two) SpringBoot takeoff road – analysis of the principle of entry
(three) SpringBoot takeoff road -YAML configuration summary (entry must know will)
(4) SpringBoot takeoff road – static resource processing
(five) SpringBoot takeoff road -Thymeleaf template engine
(6) SpringBoot takeoff road – integration jdbctemplate-druid-mybatis
(7) SpringBoot launch road – integration of SpringSecurity (Mybatis, JDBC, memory)
(eight) SpringBoot take-off path – integration Shiro detailed tutorial (MyBatis, Thymeleaf)
SpringBoot -Swagger 2 And 3
Description:
- SpringBoot takeoff road series of articles involved in the source code, are synchronized to github, there is a need for small partners, go down at will
- Github.com/ideal-20/Sp…
- Untalented and uneducated, will point to shallow knowledge, we should be a tool to see it, do not like to spray ha ~
(1) Analysis of the principle of initial dependence
(1) spring-boot-starter-parent
When we created a SpringBoot project using Maven ourselves, we needed to use the
This is SpringBoot’s parent dependency, which is a special starter that provides some of the Maven dependencies we need, while managing resource filtering for the project
To take a quick look, first press CTRL to spring-boot-starter-parent,
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.7. RELEASE</version>
<relativePath/> <! -- lookup parent from repository -->
</parent>
Copy the code
After going in, there are some resources imported content, there are some plug-ins, and then we see a parent tag, we continue to click in to have a look
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.2.7. RELEASE</version>
<relativePath>. /.. /spring-boot-dependencies</relativePath>
</parent>
Copy the code
At this point, you can’t see any other parent tags, so take a look at this file, and for a look, this is where you manage all the dependent versions in your SpringBoot application
properties
Some version information is configured in the tagdependencys
Inside the tag are dependenciesplugins
Inside the tag are some of the plug-ins involved
In the past, we used to worry about compatibility conflicts between different dependency versions. Here, SpringBoot will help us choose the most suitable dependency based on our selected SpringBoot version
<properties>.<activemq.version>5.15.12</activemq.version>
<commons-pool.version>1.6</commons-pool.version>
<jackson.version>2.10.4</jackson.version>
<javax-mail.version>1.6.2</javax-mail.version>
<log4j2.version>2.12.1</log4j2.version>
<logback.version>1.2.3</logback.version>
<mssql-jdbc.version>7.4.1. Jre8</mssql-jdbc.version>
<mysql.version>8.0.20</mysql.version>.</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot</artifactId>
<version>2.2.7. RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-test</artifactId>
<version>2.2.7. RELEASE</version>
</dependency>.<dependency>
<groupId>commons-pool</groupId>
<artifactId>commons-pool</artifactId>
<version>${commons-pool.version}</version>
</dependency>.</dependencies>
</dependencyManagement>
<build>
<pluginManagement>
<plugins>.<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>2.2.7. RELEASE</version>
</plugin>.<plugin>
<artifactId>maven-install-plugin</artifactId>
<version>${maven-install-plugin.version}</version>
</plugin>.<plugin>
<artifactId>maven-jar-plugin</artifactId>
<version>${maven-jar-plugin.version}</version>
</plugin>.</plugins>
</pluginManagement>
</build>
Copy the code
(2) spring-boot-starter-web
Then we go back to pum.xml, and there’s something different from what we’ve been doing before, which is spring-boot-starter-Web. When we initialized the component in the first article, we chose the Spring Web component. Naturally, this dependency is used to implement Web functionality
Into the spring – the boot – starter – web
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
Copy the code
The following excerpt of the XML configuration (dependency is complete) explains why the spring-boot-starter-web dependency can be used for web development. In essence, it “integrates” the coordinates of Spring-WebMVC and Spring-WebMVC that support Web development, i.e., passing dependencies
<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.7. RELEASE</version>
</parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>2.2.7. RELEASE</version>
<name>Spring Boot Web Starter</name>.<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<version>2.2.7. RELEASE</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-json</artifactId>
<version>2.2.7. RELEASE</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<version>2.2.7. RELEASE</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
<version>2.2.7. 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.6. RELEASE</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.2.6. RELEASE</version>
<scope>compile</scope>
</dependency>
</dependencies>
</project>
Copy the code
(3) This is the starter
We talked about spring-boot-starter-Web from an introductory application, where all the functional scenarios are extracted and defined as many, many initiators, through which developers can choose different initiators according to their own needs. It is very fast to set up a desired project running framework environment, the initiator naming rules are as follows:
- springboot-boot-starter-xxx
I’ll give you a few examples and try them out. I’ll give you specific instructions when I use them in future articles
Spring-boot-starter-test: Support for general test dependencies, including JUnit, Hamcrest, Mockito, and spring-test modules
Spring-boot-starter-web: supports full-stack Web development, including Tomcat and Spring-Web MVC
Spring-boot-starter-redis: supports redis key value storage databases
(2) SpringBoot startup class analysis
In addition to dependence, there is a different point from our previous Spring development is that SpringBoot has a boot class, in the preparation of the entry program, I only mentioned that this boot class is necessary to exist, seemingly simple a class, in fact, is also very mysterious, let’s analyze it together
package cn.ideal;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class SpringbootApplication {
public static void main(String[] args) { SpringApplication.run(Springboot02QuickstartApplication.class, args); }}Copy the code
(1) @ SpringbootApplication annotation
The first and most obvious annotation is the @SpringBootApplication annotation on the class, so let’s CTRL in
@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 {
......
}
Copy the code
As you can see from the above code, there are many annotations, but there are three core ones: @SpringBootConfiguration, @EnableAutoConfiguration, and @ComponentScan
Why do you say that? You can add these three comments to our previous startup class, and then execute it. If you look at it briefly, you can actually achieve the same effect as before
package cn.ideal;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.SpringBootConfiguration;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.annotation.ComponentScan;
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan
public class SpringbootApplication {
public static void main(String[] args) { SpringApplication.run(Springboot02QuickstartApplication.class, args); }}Copy the code
A: @ SpringBootConfiguration
If we click in, we can see that the @SpringBootConfiguration annotation is essentially using the @Configuration annotation of Spring
@Configuration
public @interfaceSpringBootConfiguration {... }Copy the code
You can also see the following in @Configuration
@Component
public @interfaceConfiguration {... }Copy the code
These two components should be familiar to you
- @Configuration: Specifies that the current class is a Spring Configuration class, equivalent to the applicationContext.xml file in XML
- Component.component.component.component.component.component.component.component.component.component.component.component.component.component
B: @ ComponentScan
@ComponentScan automatically scans and loads qualified components (@Component, @Controller, etc.) or bean definitions, and loads these bean definitions into IoC containers.
<! -- Enable scan -->
<context:component-scan base-package="cn.ideal"></context:component-scan>
Copy the code
The basePackages attribute specifies the scope that @ComponentScan automatically scans, just as the value attribute in this annotation does
If not specified, the default Spring framework implementation scans from the package of the class in which @ComponentScan is declared. Since this is not specified by default, this is why we place the startup class at the same level as the Controller Service package
We can also see that two filters are specified, just to mention them
@ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class), @Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
Copy the code
- TypeExcludeFilter, which facilitates the implementation of user-defined filters for Spring Test
- AutoConfigurationExcludeFilter, ignore @ Configuration and EnableAutoConfiguration so that you can make, SpringBoot not mistake the scanning to automatic assembly
C: @ EnableAutoConfiguration
This annotation is extremely important. As the name implies, it is in the format of @enablexxxxxx. There are also similar annotations @enablembeanexport, @enablesCheduling, etc
- EnableScheduling: load all Spring scheduling-framework related bean definitions into the IOC container via @import
The same is true for @enableAutoConfiguration, which uses @import to load all the bean definitions that meet automatic configuration requirements into the IOC container
So: this annotation is automatic configuration, instead of a lot of our configuration operations, adding this annotation to @SpringBootApplication means that SpringBoot automatic configuration is enabled
Let’s click in and see
First of all, there are also many annotations, so let’s focus on these two
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
(1) @ AutoConfigurationPackage
We can order in @ AutoConfigurationPackag look this annotation, which has an annotation is important @ Import (AutoConfigurationPackages. The Registrar. The class)
- @import is used to Import a component class into a container
- @ Import (AutoConfigurationPackages. The Registrar. The class) is imported into the Registrar to the component class in the Spring container
Look at Registrar, there is a registerBeanDefinitions method that imports the implementation of the component class, which is to pass in the meta information for the annotations and then get the package name
@Override
public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
register(registry, new PackageImport(metadata).getPackageName());
}
Copy the code
To sum up: The AutoConfigurationPackage annotation manages the package of the class to which it was added as an auto-configuration package
The @AutoConfigurationPackage annotation can be used to scan the main program class package and all its subpackages into the Spring container based on the package location of our starting class
(2) @ Import (AutoConfigurationImportSelector. Class)
Back to EnableAutoConfiguration, in addition to @ AutoConfigurationPackage, one of the most important, @ Import (AutoConfigurationImportSelector. Class), @ Import don’t say, so what did AutoConfigurationImportSelector? We entered the AutoConfigurationImportSelector
Because AutoConfigurationImportSelector literally called automatic configuration import selector, are we to find out about their configuration code
First of all in getAutoConfigurationEntry approach to see this one line of code:
// Get all the configuration
List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);
Copy the code
These is through getCandidateConfigurations access to configuration, we continue to jump in the past
Find getCandidateConfigurations, this approach, which calls the SpringFactoriesLoader loadFactoryNames static method of a class (note that the introduction of the first parameter)
// Get the candidate configuration
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;
}
// is called as an argument above
// Returns the annotation class that started the automatic import configuration file; EnableAutoConfiguration
protectedClass<? > getSpringFactoriesLoaderFactoryClass() {return EnableAutoConfiguration.class;
}
Copy the code
Further into this method, I have excerpted some of the important parts, and I have annotated the key parts
public static final String FACTORIES_RESOURCE_LOCATION = "META-INF/spring.factories";
public static List<String> loadFactoryNames(Class<? > factoryType,@Nullable ClassLoader classLoader) {
/ / in front of the incoming parameters for EnableAutoConfiguration. Class
/ / so factoryClassName is org. Springframework. Boot. Autoconfigure. EnableAutoConfiguration
String factoryTypeName = factoryType.getName();
/ / the factoryClassName incoming, returns all spring. The key factories file for the org. Springframework. Boot. The autoconfigure. EnableAutoConfiguration class path
return loadSpringFactories(classLoader).getOrDefault(factoryTypeName, Collections.emptyList());
}
private static Map<String, List<String>> loadSpringFactories(@Nullable ClassLoader classLoader) {
MultiValueMap<String, String> result = cache.get(classLoader);
if(result ! =null) {
return result;
}
try {
// Find all the "meta-INF /spring.factories" definitions at the topEnumeration<URL> urls = (classLoader ! =null ?
classLoader.getResources(FACTORIES_RESOURCE_LOCATION) :
ClassLoader.getSystemResources(FACTORIES_RESOURCE_LOCATION));
result = new LinkedMultiValueMap<>();
while (urls.hasMoreElements()) {
URL url = urls.nextElement();
UrlResource resource = new UrlResource(url);
// Read the contents of the file, properties is similar to a HashMap, containing the key and value of the property
Properties properties = PropertiesLoaderUtils.loadProperties(resource);
for(Map.Entry<? ,? > entry : properties.entrySet()) {// Separate multiple values with ',' in the properties file
String factoryTypeName = ((String) entry.getKey()).trim();
for (String factoryImplementationName : StringUtils.commaDelimitedListToStringArray((String) entry.getValue())) {
result.add(factoryTypeName, factoryImplementationName.trim());
}
}
}
cache.put(classLoader, result);
return result;
}
catch (IOException ex) {
throw new IllegalArgumentException("Unable to load factories from location [" +
FACTORIES_RESOURCE_LOCATION + "]", ex); }}Copy the code
Where do you start with the meta-INF /spring.factories file? Are generally under the current file by default, so follow the above code analysis to find the source package org. Springframework. Boot. Autoconfigure
Click in and see a lot of configuration content ending in AutoConfiguration, this is the root of automatic configuration, select a few simple list
. 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,\ ......Copy the code
If you look at any of them, you can see that each of them is a JavaConfig configuration class with some beans injected, so you can see that the Spring.Factories file is the root of our configuration
@enableAutoConfiguration Comments summary:
The @enableAutoConfiguration annotation is introduced under the @SpringBootApplication annotation in the startup class, which provides a feature support for configuration lookups, that is, The full name of the class of the @ EnableAutoConfiguration org. Springframework. Boot. Autoconfigure. EnableAutoConfiguration as a lookup Key, Get the corresponding set of @Configuration classes
We won’t go into the details of how these Configuration classes work, but we should add a point. Let’s go to Configuration first. Okay
org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration,\
Copy the code
@Configuration(proxyBeanMethods = false) naturally indicates that this is a Configuration class, which is consistent with our previous analysis
Want to say is this annotation: @ EnableConfigurationProperties (ServerProperties. Class)
According to the name, it is related to the Properties configuration. Go ahead and click ServerProperties
@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
......
}
Copy the code
ConfigurationProperties(prefix = “server”, ignoreUnknownFields = true)
As you can see, you specify a prefix server, and then you define a lot of things like ports and addresses and so on
So why say this? What’s the use?
This is relevant for the next article I’m going to write, which is about configuration, which we can try out here
Under the application.properties of the Resources project, we can add a configuration like this:
server.port=9090
Copy the code
In this line configuration, the port number is modified, is not very magical
That’s what we were trying to say, The server is the @configurationProperties (prefix = “server”, ignoreUnknownFields = true) prefix. Port is the port defined below, where SpringBoot maps properties starting with Server in the configuration file to fields of that class
(2) SpringApplication.run
Going back to the startup class, let’s mention springApplication.run
@SpringBootApplication
public class SpringbootApplication {
public static void main(String[] args) { SpringApplication.run(SpringbootApplication.class, args); }}Copy the code
This part of the content of the design of the content is more, in the later specialized source code analysis, a simple understanding of the role of the entry on the line
-
Decide whether your application is a normal project or a Web project
-
Load initializers and listeners and set them in the Initializers property
-
Infer and set the definition class of the main method to find the running main class
(3) Ending
If there is any deficiency in the article, you are welcome to leave a message to exchange, thank friends for their support!
If it helps you, follow me! If you prefer the way of reading articles on wechat, you can follow my official account
We don’t know each other here, but we are working hard for our dreams
A adhere to push original development of technical articles of the public number: ideal more than two days