🌹 welcome wechat attention [Java programming], progress a little bit every day, precipitation technology to share knowledge.
Interview season “Spring Boot” automatic assembly
SpringBoot has now become a must-have skill for Java programmers, whether you are new graduates or job-hopping programmers, mastering SpringBoot is a must. I recently decided to use SpringBoot’s automatic configuration principle to implement a class library, take this opportunity to share with you some of the techniques I used. Approaching the autumn enrollment season, I hope this article can bring some help to the students of autumn enrollment.
Come on! Three questions of the Soul:
- What is auto-assembly?
- What does autowiring do for us?
- How to achieve automatic assembly?
Can you do it? Panic? Doubt life? Hold! Please follow me to find out the answer.
SpringBoot is automatically configured
When you start learning SpringBoot, you know that we just need to: Properties or application.yml, with a little bit of configuration, a Web project can be started and used. SpringBoot automatically assembs a lot of Bean definitions for us and finally generates beans from Bean factories to be cached in containers for you to use. The following provides you with more configuration items in addition to some common configurations, you can refer to the official documentation.
SpringBoot configuration items
Let’s get into the body and see how SpringBoot implements auto-assembly.
SpringBoot start class
@SpringBootApplication
public class App {
public static void main(String[] args) { SpringApplication.run(App.class, args); }}Copy the code
This little note helps us launch SpringBoot, which by default configures a number of auto-configuration classes. The most important of these is the @SpringBootApplication annotation, so let’s click on it.
@SpringBootApplication
@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
Here are three notes:
- @springBootConfiguration: SpringBoot configuration class. Annotated on a class to indicate that it is a SpringBoot configuration class (equivalent to an.xml file in XML mode).
- @enableAutoConfiguration: Enable the automatic configuration class, the essence of SpringBoot.
- @ComponentScan: Enables and sets the packet scanning path in XML.
@EnableAutoConfiguration
EnableAutoConfiguration: tells SpringBoot to enable automatic configuration so that the automatic configuration takes effect.
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {
Copy the code
- @autoConfigurationPackage: Automatic configuration package
- @import: Import automatically configured components
- @import: The @import annotation is usually used when a class is not injected into the IOC container, but needs to obtain the bean corresponding to the class. There are many ways to add to an IOC container, including @bean annotations, but the @import annotation is much more convenient for quick Import.
@AutoConfigurationPackage
static class Registrar implements ImportBeanDefinitionRegistrar.DeterminableImports {
@Override
public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
register(registry, new PackageImport(metadata).getPackageName());
}
Copy the code
It registers the definition of a Bean and returns the package components of the siblings and children of the current main program class. If you write a class above the APP class, SpringBoot won’t load it for you and report a 404 problem, which is why we put the APP at the top level of the project.
- SpringApplication.run(App.class, args); Why pass in the main launch class?
- One aspect is to parse the package according to the class and scan the peer and subordinate classes.
@Import
@Import(AutoConfigurationImportSelector.class)
Copy the code
Here to the core of the automatic assembly, not far from success, let’s watch, direct AutoConfigurationImportSelector through inheritance DeferredImportSelector, ImportSelector rewrite selectImports method.
This method lays the core function logic of SpringBoot automatic batch assembly.
@Override
public String[] selectImports(AnnotationMetadata annotationMetadata) {
if(! isEnabled(annotationMetadata)) {return NO_IMPORTS;
}
AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader
.loadMetadata(this.beanClassLoader);
AnnotationAttributes attributes = getAttributes(annotationMetadata);
List<String> configurations = getCandidateConfigurations(annotationMetadata,
attributes);
configurations = removeDuplicates(configurations);
Set<String> exclusions = getExclusions(annotationMetadata, attributes);
checkExcludedClasses(configurations, exclusions);
configurations.removeAll(exclusions);
configurations = filter(configurations, autoConfigurationMetadata);
fireAutoConfigurationImportEvents(configurations, exclusions);
return StringUtils.toStringArray(configurations);
}
Copy the code
You can see getCandidateConfigurations () method, Public static final String FACTORIES_RESOURCE_LOCATION = “meta-INF /spring.factories” This external file, by default, contains a number of automatically configured classes whose definitions will be loaded in batches by SpringBoot into the Bean definition Map for instance creation. As follows:
AutoConfigurationMetadata
Provides access to meta-data written by the auto-configure annotation processor.
Provides access to metadata written to auto-configuration annotations.
What are the things under this Path? I’ll give you a few:
#Thu Jun 14 11:34:18 UTC 2018 org.springframework.boot.autoconfigure.web.client.RestTemplateAutoConfiguration.AutoConfigureAfter=org.springframework.b oot.autoconfigure.http.HttpMessageConvertersAutoConfiguration org.springframework.boot.autoconfigure.data.cassandra.CassandraReactiveDataAutoConfiguration.ConditionalOnClass=com.data stax.driver.core.Cluster,org.springframework.data.cassandra.core.ReactiveCassandraTemplate,reactor.core.publisher.Flux org.springframework.boot.autoconfigure.data.solr.SolrRepositoriesAutoConfiguration.ConditionalOnClass=org.apache.solr.cl ient.solrj.SolrClient,org.springframework.data.solr.repository.SolrRepository org.springframework.boot.autoconfigure.jersey.JerseyAutoConfiguration.AutoConfigureBefore=org.springframework.boot.autoc onfigure.web.servlet.DispatcherServletAutoConfiguration org.springframework.boot.autoconfigure.couchbase.CouchbaseAutoConfiguration.ConditionalOnClass=com.couchbase.client.java .CouchbaseBucket,com.couchbase.client.java.Cluster org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration.ConditionalOnClass=org.springframework.amqp.rabbit.c ore.RabbitTemplate,com.rabbitmq.client.ChannelCopy the code
These things are not the focus of this article, I will not go into detail. Simply autoConfigurationMetadata this parameter will be in the back of the filter method is used to, and the filter method is processing your configuration class in certain xxxconditionOnClass, This information about the classes used in the configuration classes should be provided by the above methods.
Gets candidate configuration items
See article knowledge meaning: getCandidateConfigurations obtain candidate configuration items, the candidate configuration item is spring. The configuration items under the factories.
List<String> configurations = getCandidateConfigurations(annotationMetadata,attributes);
Copy the code
Let’s look at the details of this method and what it does. Translate the following sentence (return autoconfigure class name)
In the loadSpringFactorise method edges are looped through such as reading the configuration information under Spring.Factories and caching it into the Map.
- The first arrow first loads some auto-configuration classes at once to reduce reloading and improve efficiency.
- The second arrow goes to that path and finds the Spring.Factories and reads the auto-configuration classes set up there
- The third arrow writes the read results to the Map cache
Other methods
After reading the automatic configuration information, it goes through the following methods, mainly to de-process it.
- To prevent self-written autowiring classes and Springboot assembly classes from repeating, perform deduplication.
configurations = removeDuplicates(configurations);
Copy the code
- Read the @SpringBootApplication exclude property to exclude auto-loading classes.
Set<String> exclusions = getExclusions(annotationMetadata, attributes);
Copy the code
- Handle comments such as @conditionalonclass in the automatic configuration class. If not, the configuration will not take effect.
checkExcludedClasses(configurations, exclusions);
configurations.removeAll(exclusions);
configurations = filter(configurations, autoConfigurationMetadata);
Copy the code
Trigger the automatic configuration import event
generalizations
When we use the @enableAutoConfiguration annotation to enable auto-assembly, there are actually many XXXAutoConfiguration classes performing the assembly work. These XXXAutoConfiguration classes are configured in the meta-INF/spring.Factories file in the spring-boot-Autoconfigure JAR. @enableAutoConfiguration Creates XXXAutoConfiguration beans through the SpringFactoriesLoader mechanism. The beans of XXXAutoConfiguration are executed in turn and determine whether the corresponding beans need to be created for injection into the Spring container.
In each XXXAutoConfiguration class, ConditionOnXXX makes use of several types of condition@conditiononxxx to make judgments about the current application environment. For example, the application is a Web application, the classpath path contains the corresponding class, and the Spring container already contains the corresponding type of bean. If all the criteria are true, XXXAutoConfiguration will assume that the bean needs to be injected into the Spring container, otherwise it will be ignored.
More wonderful good article in: Java programming way 🎁 welcome friends to pay attention to! 🌹