You can learn from this article as follows:
-
First of all, this article must have a certain foundation before you can read it. If you are getting started, I suggest you start with a video or a book.
-
Second, you can know the configuration principle of SpringBoot from this article
-
In addition, the follow-up meeting will continue to write SpringBoot articles
1, First, let's look at the Bean configuration of the Spring program
First, let's learn what bean configuration is
-
bean configuration is a process of writing our own code into the Spring container
-
Spring has three ways to configure beans
- java based
- XMl based
- Component scan based
-
Recall that Spring inversion of control is a way to produce or obtain specific objects through description (XML or annotation) and through a third party. In Spring, the IoC container implements control inversion, and its implementation method is dependency injection (DI)
- How to say, we used to write java code for new, but now we don't need it. Then we can use it after (DI) injection
- SpringBoot is automatic configuration (automatic scanning of components can) and automatic injection (Autowired). It doesn't matter if you don't understand this sentence. You'll understand it later.
1. java based configuration
- Use the @ Configuration annotation to declare the class as a Configuration class,
- Then use the @ Bean annotation to add the instance object returned by the method to the context of the container
- @The bean ID of the bean annotation is the method name by default. If you want to specify a name, you can set it through the name attribute
@Configuration public class WebConfig { @Bean public User user() { return new User("Hello world"); } }
2. Xml based configuration
- It is not applicable to any annotation and can be configured by yourself
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd"> <bean class="com.kuang.User" id="user"> <constructor-arg ref="hello"/> </bean> <bean class="com.kuang.User" id="hello"></bean> </beans>
3. Type of component scan
It is configured from two aspects:
- Component scanning (configuring a normal class as a Bean using the Component annotation)
- Automatic assembly (use @ Autowired (automatic injection) to make Spring meet Bean dependencies)
- Also note some @ ComponentScan ("paths") for configuring scanning
1. Use the Component annotation to configure a normal class as a Bean
@Component public class Hello { public void HelloWorld(String name){ System.out.println("Hello" + name); } }
2. Use @ Autowired (automatic injection) to make Spring meet Bean dependencies
@Component public class User { @Autowired private Hello hello; public void hello() { hello.HelloWorld(); } }
2, Let's take a look at a configuration implemented by SpringBoot
The following sentences should be memorized:
- SpringBoot is essentially a Spring container, but it implements different functions by importing dependencies
- The code we write is called components: we can usually put it into the spring boot container with the following annotations: write them through annotations
- @Component: refers to various components
- @Component.
- @Controller: control layer
- @Service: business layer
- @Repository: data access layer
- And the following SpringBoot
- @Autowired, don't explain first
- @SpringBootConfiguration will not be explained first
- And wait---------
- Then, it can be configured by manually entering the container through @ ComponentScan or automatically scanning the package through @ AutoConfigurationPackage
- Then we can use @ Autowired, and Spring needs to use a series of xml or other configurations
1. Create project first
Whatever project you create, the focus here is on understanding the principles, not the project.
- I used a project I created before
2. Analysis project
(1) Click our parent dependency (Ctrl + left mouse button)
(2) The same thing (click in)
- The point is this dependence
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-dependencies</artifactId> <version>2.5.6</version> </parent>
(3) To sum up
- This is the real management SpringBoot Where the application depends on the version, SpringBoot Version control center of; - In the future, we do not need to write the version by default when importing dependencies. However, if the imported package is not managed in the dependency, you need to manually configure the version;
3. Launcher: spring boot starter
The dependency we import is the initiator
- For example, click artifactId: This is the initiator of jwt
<dependency> <groupId>io.jsonwebtoken</groupId> <artifactId>jjwt</artifactId> <version>0.9.0</version> </dependency>
4. Start class analysis
Focus on here, focus on here, focus on here: first of all, the road may be a little messy, but I suggest you look at every word carefully
@SpringBootApplication @MapperScan("com.xxxx.server.mapper") public class yebApplication { public static void main(String[] args) { SpringApplication.run(yebApplication.class,args); } }
(1) Click this spring boot application annotation to see
I see these notes on it
@SpringBootConfiguration @EnableAutoConfiguration @ComponentScan( excludeFilters = {@Filter( type = FilterType.CUSTOM, classes = {TypeExcludeFilter.class} ), @Filter( type = FilterType.CUSTOM, classes = {AutoConfigurationExcludeFilter.class} )} )
- @ComponentScan
-
This annotation is important in Spring and corresponds to the elements in the XML configuration.
-
Function: automatically scan and load qualified components or beans, and load the bean definition into the IOC container
-
- @Spring boot configuration: click in to see
- Function: the configuration class of SpringBoot is marked on a class to indicate that it is a SpringBoot configuration class;
- Let's go on to this annotation to see:
- The @ Configuration here indicates that this is a Configuration class, which is the xml Configuration file corresponding to Spring;
- The @ Component inside shows that the startup class itself is just a Component in Spring and is responsible for starting the application!
(2) Go back to the spring boot application annotation and continue
- @Enable autoconfiguration note: enable autoconfiguration
- Here's one thing to remember: in the future, we need to enable XXX (remember, it doesn't matter if we don't understand)
- Click enable autoconfiguration again. The following are more important
- 1)@AutoConfigurationPackage
- (1) Click @ AutoConfigurationPackage to see: the exposure is as follows:
@Import({Registrar.class})
public @interface AutoConfigurationPackage {
} - (2) @ import: Spring bottom annotation @ import, import a component into the container: Registrar.class. Function: scan all components in the package of the main startup class and all sub packages under the package to the Spring container;
- (1) Click @ AutoConfigurationPackage to see: the exposure is as follows:
- 2) Let's look at @ Import({AutoConfigurationImportSelector.class}): AutoConfigurationImportSelector: automatically configure the import selector. What component selectors will it import? Let's click this class to see the source code:
- (1) There is a method in this class: getCandidateConfigurations
- (2) This method also calls the static method of the springfactoryesloader class! We enter the loadFactoryNames() method of the springfactoryesloader class
- (3) Let's continue to click to view the loadSpringFactories method
- (4) Find a file that appears many times: spring.factories. Search it globally
- 1)@AutoConfigurationPackage
protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) { //The getSpringFactoriesLoaderFactoryClass () method here //The returned annotation class is the annotation class that we first saw to start the automatic import configuration file; EnableAutoConfiguration 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; }
public static List<String> loadFactoryNames(Class<?> factoryClass, @Nullable ClassLoader classLoader) { String factoryClassName = factoryClass.getName(); //Here it calls the loadSpringFactories method again return (List)loadSpringFactories(classLoader).getOrDefault(factoryClassName, Collections.emptyList()); }
private static Map<String, List<String>> loadSpringFactories(@Nullable ClassLoader classLoader) { //After obtaining the classLoader, we can see that what we get here is the class itself marked with EnableAutoConfiguration MultiValueMap<String, String> result = (MultiValueMap)cache.get(classLoader); if (result != null) { return result; } else { try { //Go to get a resource "META-INF/spring.factories" Enumeration<URL> urls = classLoader != null ? classLoader.getResources("META-INF/spring.factories") : ClassLoader.getSystemResources("META-INF/spring.factories"); LinkedMultiValueMap result = new LinkedMultiValueMap(); //Traverse the read resources and encapsulate them into a property while(urls.hasMoreElements()) { URL url = (URL)urls.nextElement(); UrlResource resource = new UrlResource(url); Properties properties = PropertiesLoaderUtils.loadProperties(resource); Iterator var6 = properties.entrySet().iterator(); while(var6.hasNext()) { Entry<?, ?> entry = (Entry)var6.next(); String factoryClassName = ((String)entry.getKey()).trim(); String[] var9 = StringUtils.commaDelimitedListToStringArray((String)entry.getValue()); int var10 = var9.length; for(int var11 = 0; var11 < var10; ++var11) { String factoryName = var9[var11]; result.add(factoryClassName, factoryName.trim()); } } } cache.put(classLoader, result); return result; } catch (IOException var13) { throw new IllegalArgumentException("Unable to load factories from location [META-INF/spring.factories]", var13); } } }
Spring.factories file: in this location, we open spring.factories according to the source and see many automatically configured files; This is the root of automatic configuration!
To sum up, the automatic scanning is completed through @ EnableAutoConfiguration, and then the principle is @ Import({AutoConfigurationImportSelector.class}): this class works. Go to find the file spring.factories under the configuration for automatic configuration
(3) Here's a general understanding of webmvcoautoconfiguration
- If you use idea, you can use Ctrl + n to realize global search: webmvcoautoconfiguration, and then view it
It's full of Bean configurations - There are many configurations here: such as redirection, controller and so on. Next, I will explain this input
(4) Start learning method run
-
The analysis of this method is mainly divided into two parts: one is the instantiation of spring application, and the other is the execution of run method
-
The SpringApplication class mainly does the following four things:
-
Infer whether the type of application is a normal project or a Web project
-
Find and load all available initializers and set them in the initializers property
-
Find all application listeners and set them to the listeners property
-
Infer and set the definition class of the main method, and find the main class to run
-
-
Look at the method
5,WebMvcAutoConfiguration
After we have a general understanding of the previous content, we need to have an in-depth understanding
Let's take Http encoding autoconfiguration (Http encoding autoconfiguration) as an example to facilitate analysis (you can take thymeleaf autoconfiguration as an example), etc
//Indicates that this is a configuration class. Like the previously written configuration file, you can also add components to the container; @Configuration //Start the ConfigurationProperties function of the specified class; //Enter the HttpProperties view and bind the corresponding values in the configuration file with HttpProperties; //And add HttpProperties to the ioc container @EnableConfigurationProperties({HttpProperties.class}) //Spring underlying @ Conditional annotation //According to different conditions, if the specified conditions are met, the configuration in the whole configuration class will take effect; //This means to judge whether the current application is a web application. If so, the current configuration class will take effect @ConditionalOnWebApplication( type = Type.SERVLET ) //Judge whether the current project has this class CharacterEncodingFilter; Filter for garbled code resolution in spring MVC; @ConditionalOnClass({CharacterEncodingFilter.class}) //Judge whether there is a configuration in the configuration file: spring.http.encoding.enabled; //If it does not exist, the judgment is also valid //Even if pring.http.encoding.enabled=true is not configured in our configuration file, it will take effect by default; @ConditionalOnProperty( prefix = "spring.http.encoding", value = {"enabled"}, matchIfMissing = true ) public class HttpEncodingAutoConfiguration { //He has mapped to the SpringBoot configuration file private final Encoding properties; //When there is only one constructor with parameters, the value of the parameter will be taken from the container public HttpEncodingAutoConfiguration(HttpProperties properties) { this.properties = properties.getEncoding(); } //Add a component to the container. Some values of this component need to be obtained from properties @Bean @ConditionalOnMissingBean //Determine that the container does not have this component? public CharacterEncodingFilter characterEncodingFilter() { CharacterEncodingFilter filter = new OrderedCharacterEncodingFilter(); filter.setEncoding(this.properties.getCharset().name()); filter.setForceRequestEncoding(this.properties.shouldForce(org.springframework.boot.autoconfigure.http.HttpProperties.Encoding.Type.REQUEST)); filter.setForceResponseEncoding(this.properties.shouldForce(org.springframework.boot.autoconfigure.http.HttpProperties.Encoding.Type.RESPONSE)); return filter; } //. . . . . . . }