The underlying principle of SpringBoot automatic configuration (hand tear @SpringBootApplication annotation source code)

Insert picture description here
Let's start with the @SpringBootApplication annotation of the main program class.
First, we click into @SpringBootApplication:
Insert picture description here
we see that it is composed of four meta annotations @Target, @Retention, @Documented, and @Inherited and @SpringBootConfiguration, @EnableAutoConfiguration, @ComponentScan ( ) An annotation composed of three annotations;
we don't need to say more about meta annotations. Next, I will explain the three annotations @SpringBootConfiguration, @EnableAutoConfiguration, and @ComponentScan.
Let's first talk about two simple annotations @SpringBootConfiguration and @ComponentScan annotations, and finally talk about the core and most troublesome annotation @EnableAutoConfiguration annotation.

一.@SpringBootConfiguration

We click into @SpringBootConfiguration:
Insert picture description here
we found that it is composed of meta-annotations and @Configuration, that is, @Configuration annotations. What is @Configuration? It means that it is currently a configuration class.
In other words, our MainApplication main program class is also a configuration class, but it is a core configuration class.

二.@ComponentScan

@ComponentScan we all know that it is a package scanning annotation, which specifies what to scan.

三.@EnableAutoConfiguration

Here comes, the most important thing is finally here.
Closer to home, we click into the @EnableAutoConfiguration annotation: we
Insert picture description here
found that it is composed of 4 meta annotations and @AutoConfigurationPackage, @Import({AutoConfigurationImportSelector.class}) annotations.
Let's talk about the @AutoConfigurationPackage annotation first, and then the role of the component imported by @Import({AutoConfigurationImportSelector.class}).

1.@AutoConfigurationPackage

We click into the @AutoConfigurationPackage annotation: we
Insert picture description here
find that it is actually an @Import annotation. What is the imported Registrar? Let's click in and take a look:
Insert picture description here

I found that it has two methods. In fact, Registrar is to register components in batches in the container. Because it is too troublesome to import one by one with import, so write a piece of code to register
in batches; we put a breakpoint on the first method, you can see Which components does it register:
Insert picture description here
This method has two parameters, as follows:
Insert picture description here
AnnotationMetadata is the source information of the annotation, and the annotation refers to @AutoConfigurationPackage. The source information of the annotation indicates where the annotation is marked and what each attribute value of it is , This annotation is the annotation in @SpringBootApplication, @SpringBootApplication is marked on the MainApplication main program class, so it is actually marked on the MainApplication main program class.
We can open the metadata to view its information during debugging: we
Insert picture description here
find that it is indeed on the main program class, and then we continue to talk about this method. This method here has a new PackageImports:
Insert picture description here
equivalent to getting our annotation source information to get ours The package name, we can let it calculate what the package name we get:
Insert picture description here
Insert picture description here
you can see that the package path where the MainApplication main program class is calculated.
Let's talk about that method. After it gets our package path, it gets the package name of the main program class, then encapsulates the package name into an array, and then registers it for us in the container.
In other words, our Registrar is equivalent to registering all the components under a certain package into the container in batches.
@AutoConfigurationPackage small summary:

  • Use Registrar to import a series of components into the container
  • Import all the components in the package where the MainApplication main program class is located

2.@Import({AutoConfigurationImportSelector.class})

Use the selector to import some components into the container in batches.
We click into the AutoConfigurationImportSelector:
Insert picture description here
the array returned by our selectImports method specifies which components to import into the container, and the getAutoConfigurationEntry method is called in the selectImports method, so we now
Insert picture description here
Let’s study the getAutoConfigurationEntry method, enter the getAutoConfigurationEntry method, and put a breakpoint on the body of the getAutoConfigurationEntry method: debug run, when we run one by one to get the configuration, we can see that there are 130 configurations:
Insert picture description here
click on the configurations and you will find 130 full class names. Explain that all the 130 components specified by the full class name are to be imported into our container:
Insert picture description here
then how do we know that these 130 are like this? We give a breakpoint to the getCandidateConfigurations method and re-debug:
Insert picture description here
enter the method and find that it actually uses these Spring factory loaders to load some things:
Insert picture description here
click into SpringFactoriesLoader.loadFactoryNames:
Insert picture description here
then click into (List)loadSpringFactories(classLoaderToUse ):
Insert picture description here
Finally use this method to load all the components for us, then where do we load all the components from?
We put a breakpoint on the loadSpringFactories method body and re-debug:
Insert picture description here
you can see that it loads a resource file here, the location is: META-INF/spring.factories
In other words, all files in the META-INF/spring.factories location in our current system are scanned by default;
now we look at the META-INF under the spring-boot-autoconfigure-2.4.1.jar package:
Insert picture description here

Found that it has a spring.factories file:
Insert picture description here
check the content of the file, there is a configuration item, org.springframework.boot.autoconfigure.EnableAutoConfiguration:
Insert picture description here
from line 22 to line 151, a full 130 lines of content:
Insert picture description here
this is our 130 components that need to be loaded , They are all here, and they are all hard-coded in this configuration file, which means that all the configuration classes loaded in the container will be loaded when spring-boot is started.

But is the reality like this? Is it really necessary to load all 130 components into the container?
Actually not, our SpringBoot has the function of enabling automatic configuration items on demand.
Although all the automatic configurations of our 130 scenes are loaded by default when they are started. xxxxAutoConfiguration, but will eventually be configured on demand, according to the conditional assembly rules (@Conditional).
For example, we click into AopAutoConfiguration:
Insert picture description here

Insert picture description here

In this class, we did not import the Advice class in org.aspectj.weaver, so its internal class AspectJAutoProxyingConfiguratio will not take effect:
Insert picture description here

Guess you like

Origin blog.csdn.net/MrYushiwen/article/details/112095242