Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

What is the principle of SpringBoot automatic assembly?

2025-01-19 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/03 Report--

This article introduces you what is the principle of SpringBoot automatic assembly, the content is very detailed, interested friends can refer to, hope to be helpful to you.

Every time SpringBoot is asked, the interviewer likes to ask this question very much: "tell me about the principle of SpringBoot automatic assembly?" .

I think we can answer from the following aspects:

What is SpringBoot automatic assembly?

How does SpringBoot realize automatic assembly? How to achieve on-demand loading?

How to implement a Starter?

This article is not in-depth, friends can also directly use debug to look at the source code of the SpringBoot auto-assembly part.

Preface

Friends who have used Spring must have the fear of being dominated by XML configuration. Even if annotation-based configuration is introduced after Spring, we still need to use XML or Java for explicit configuration when we turn on some Spring features or introduce third-party dependencies.

For instance. When there is no Spring Boot, we write a RestFul Web service, and first we need to configure it as follows.

Configurationpublic class RESTConfiguration {@ Bean public View jsonTemplate () {MappingJackson2JsonView view = new MappingJackson2JsonView (); view.setPrettyPrint (true); return view;} @ Bean public ViewResolver viewResolver () {return new BeanNameViewResolver ();}}

Spring-servlet.xml

However, for the Spring Boot project, we only need to add related dependencies without configuration, by starting the following main method.

@ SpringBootApplicationpublic class DemoApplication {public static void main (String [] args) {SpringApplication.run (DemoApplication.class, args);}}

In addition, we can set the project through Spring Boot's global configuration file application.properties or application.yml, such as changing the port number, configuring the JPA properties, and so on.

Why is Spring Boot so sour to use? This is thanks to its automatic assembly. Automatic assembly can be said to be the core of Spring Boot, so what on earth is automatic assembly?

What is SpringBoot automatic assembly?

When we talk about auto-assembly now, we usually associate it with Spring Boot. However, in fact, Spring Framework has already implemented this feature. Spring Boot is only on its basis, through the way of SPI, to do further optimization.

SpringBoot defines a set of interface specifications that stipulate that SpringBoot will scan the META-INF/spring.factories file in the externally referenced jar package at startup, load the type information configured in the file into the Spring container (here it involves the JVM class loading mechanism and the container knowledge of Spring), and perform various operations defined in the class. For external jar, you only need to follow the standards defined by SpringBoot to put your own functional devices into SpringBoot.

Without Spring Boot, if we need to introduce third-party dependencies, we need to configure them manually, which is very troublesome. However, in Spring Boot, we can simply introduce a starter. For example, if you want to use redis in your project, just introduce the corresponding starter into the project.

Org.springframework.boot spring-boot-starter-data-redis

With the introduction of starter, we can use the functionality provided by third-party components with a few annotations and some simple configuration.

In my opinion, auto-assembly can be understood simply as: a certain function can be achieved with the help of Spring Boot through annotations or some simple configuration.

How does SpringBoot realize automatic assembly?

Let's take a look at SpringBootApplication, the core annotation of SpringBoot.

@ Target ({ElementType.TYPE}) @ Retention (RetentionPolicy.RUNTIME) @ Documented@Inherited@SpringBootConfiguration@ComponentScan@EnableAutoConfigurationpublic @ interface SpringBootApplication {} @ Target ({ElementType.TYPE}) @ Retention (RetentionPolicy.RUNTIME) @ Documented@Configuration / / it is actually a configuration class public @ interface SpringBootConfiguration {}

You can probably think of @ SpringBootApplication as a collection of @ Configuration, @ EnableAutoConfiguration, @ ComponentScan annotations. According to the SpringBoot website, the functions of these three annotations are:

@ EnableAutoConfiguration: enable the automatic configuration mechanism of SpringBoot

Configuration: allows you to register additional bean or import other configuration classes in context

@ ComponentScan: scan the bean annotated by @ Component (@ Service,@Controller). By default, the annotation scans all classes under the package where the startup class resides. You can customize not to scan some bean. As shown in the following figure, TypeExcludeFilter and AutoConfigurationExcludeFilter are excluded from the container.

@ EnableAutoConfiguration is an important annotation for automatic assembly. Let's start with this annotation.

@ EnableAutoConfiguration: the core annotation for automatic assembly

EnableAutoConfiguration is just a simple annotation, and the core functions of automatic assembly are actually implemented through the AutoConfigurationImportSelector class.

@ Target ({ElementType.TYPE}) @ Retention (RetentionPolicy.RUNTIME) @ Documented@Inherited@AutoConfigurationPackage / / function: register the desired components under the main package in the container @ Import ({AutoConfigurationImportSelector.class}) / / load the auto-assembly class xxxAutoconfigurationpublic @ interface EnableAutoConfiguration {String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration"; Class [] exclude () default {}; String [] excludeName () default {};}

Now let's focus on what the AutoConfigurationImportSelector class does.

AutoConfigurationImportSelector: loading auto-assembly classes

The inheritance system of the AutoConfigurationImportSelector class is as follows:

Public class AutoConfigurationImportSelector implements DeferredImportSelector, BeanClassLoaderAware, ResourceLoaderAware, BeanFactoryAware, EnvironmentAware, Ordered {} public interface DeferredImportSelector extends ImportSelector {} public interface ImportSelector {String [] selectImports (AnnotationMetadata var1);}

As you can see, the AutoConfigurationImportSelector class implements the ImportSelector interface, that is, the selectImports method in this interface, which is mainly used to obtain the fully qualified class names of all eligible classes that need to be loaded into the IoC container.

Private static final String [] NO_IMPORTS = new String [0]; public String [] selectImports (AnnotationMetadata annotationMetadata) {/ /. Determine whether the auto-assembly switch turns on if (! this.isEnabled (annotationMetadata)) {return NO_IMPORTS;} else {/ /. Get all the bean AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader.loadMetadata (this.beanClassLoader); AutoConfigurationImportSelector.AutoConfigurationEntry autoConfigurationEntry = this.getAutoConfigurationEntry (autoConfigurationMetadata, annotationMetadata); return StringUtils.toStringArray (autoConfigurationEntry.getConfigurations ());}}

Here we need to focus on the getAutoConfigurationEntry () method, which is mainly responsible for loading the autoconfiguration class.

The method call chain is as follows:

Now let's analyze it in detail with the source code of getAutoConfigurationEntry ():

Private static final AutoConfigurationEntry EMPTY_ENTRY = new AutoConfigurationEntry (); AutoConfigurationEntry getAutoConfigurationEntry (AutoConfigurationMetadata autoConfigurationMetadata, AnnotationMetadata annotationMetadata) {/ /. If (! this.isEnabled (annotationMetadata)) {return EMPTY_ENTRY;} else {/. AnnotationAttributes attributes = this.getAttributes (annotationMetadata) / /. List configurations = this.getCandidateConfigurations (annotationMetadata, attributes); /. Configurations = this.removeDuplicates (configurations); Set exclusions = this.getExclusions (annotationMetadata, attributes); this.checkExcludedClasses (configurations, exclusions); configurations.removeAll (exclusions); configurations = this.filter (configurations, autoConfigurationMetadata); this.fireAutoConfigurationImportEvents (configurations, exclusions); return new AutoConfigurationImportSelector.AutoConfigurationEntry (configurations, exclusions);}}

Step 1:

Determine whether the automatic assembly switch is turned on. Default spring.boot.enableautoconfiguration=true, which can be set in application.properties or application.yml

Step 2:

Used to get exclude and excludeName in EnableAutoConfiguration annotations.

Step 3

Get all the configuration classes that need to be automatically assembled, and read META-INF/spring.factories

Spring-boot/spring-boot-project/spring-boot-autoconfigure/src/main/resources/META-INF/spring.factories

You can see from the figure below that the configuration contents of this file have been read by us. The purpose of XXXAutoConfiguration is to load components on demand.

Not only the META-INF/spring.factories under this dependency is read, but all META-INF/spring.factories under Spring Boot Starter are read.

So, you can clearly see that the Spring Boot Starter of the druid database connection pool creates the META-INF/spring.factories file.

If we want to create a Spring Boot Starter ourselves, this step is essential.

Step 4:

At this point, the interviewer may ask you, "with so many configurations in spring.factories, do you have to load them all every time you start?" .

Obviously, this is unrealistic. When we debug to the back, you will find that the value of configurations is getting smaller.

Because this step goes through filtering, and all the conditions in @ ConditionalOnXXX are met, this class will not take effect.

@ Configuration// checks whether RabbitTemplate and Channel exist / / before loading @ ConditionalOnClass ({RabbitTemplate.class, Channel.class}) @ EnableConfigurationProperties (RabbitProperties.class) @ Import (RabbitAnnotationDrivenConfiguration.class) public class RabbitAutoConfiguration {}

Interested children's shoes can learn more about the conditions provided by Spring Boot.

@ ConditionalOnBean: when the container has a specified Bean

@ ConditionalOnMissingBean: when no Bean is specified in the container

@ ConditionalOnSingleCandidate: when there is only one specified Bean in the container, or although there are multiple, the preferred Bean is specified.

@ ConditionalOnClass: when there is a specified class under the classpath

@ ConditionalOnMissingClass: when no class is specified in the classpath

@ ConditionalOnProperty: whether the specified property has the specified value

@ ConditionalOnResource: whether the classpath has the specified value

@ ConditionalOnExpression: based on SpEL expression as a judgment condition

@ ConditionalOnJava: based on the Java version as a judgment condition

@ ConditionalOnJndi: the difference is at the specified location under the condition that JNDI exists

ConditionalOnNotWebApplication: under the condition that the current project is not a Web project

@ ConditionalOnWebApplication: under the condition that the current project is for Web purposes

How to implement a Starter

Let's just talk about it instead of practicing fake games, so let's do a starter now to implement a custom thread pool.

First step, create the threadpool-spring-boot-starter project

The second step is to introduce Spring Boot dependencies

Step 3, create a ThreadPoolAutoConfiguration

Step 4, create the META-INF/spring.factories file under the resources package of the threadpool-spring-boot-starter project

Finally, the new project introduces threadpool-spring-boot-starter.

The test passed!

Spring Boot enables automatic assembly through @ EnableAutoConfiguration, and finally loads the automatic configuration class in META-INF/spring.factories through SpringFactoriesLoader to achieve automatic assembly. The automatic configuration class is actually the configuration class loaded on demand through @ Conditional. If you want it to take effect, you must introduce the spring-boot-starter-xxx package to achieve starting dependence.

What is the principle of SpringBoot automatic assembly is shared here, I hope that the above content can be of some help to you, can learn more knowledge. If you think the article is good, you can share it for more people to see.

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report