SpringBoot Series @SpringBoot Application Source Parsing

Posted by iconicCreator on Thu, 22 Aug 2019 10:35:21 +0200

Personal blog: haichenyi.com. Thank you for your attention

In the last article, there was very little content about how SpringBook's underlying layers depend. This article describes how SpringBoot's underlying source code is implemented.

_Begins at the entrance to SpringBook. As I said in the first article, it's better to put the entry file under the outermost package, but the reasons are not elaborated.

Let's talk about the principle of this @SpringBootApplication annotation, click in and see:

As follows:

The three main annotations are as follows:

  • @SpringBootConfiguration
  • @EnableAutoConfiguration
  • @ComponentScan

@SpringBootConfiguration

_SpringBoot Configuration This annotation is implemented by the Configuration annotation.

@Configuration

_Judging from the name, this annotation is related to Spring Boot configuration, @Configuration, which is a annotation at the bottom of Spring. It used to configure xml. Spring Boot recommends that we use configuration classes to describe configuration. What is the configuration class? Classes tagged with @Configuration.

_Configuration This annotation is implemented by Component annotation.

@Component

The meaning of this annotation is to add the current configuration class to the spring container to represent a component.

@EnableAutoConfiguration

_Enable AutoConfiguration This annotation is implemented by AutoConfiguration Package and **@Import ({AutoConfiguration Import Selector.class})** annotations

@AutoConfigurationPackage

_This annotation shows from the name that it is an automatic configuration package. What does that mean? In the first article, we said that entries should be placed in the outermost package. As for the reason, we have already mentioned that SpringBoot automatically scans the package of the class labeled by the boot class @SpringBootApplication and all the components in all the subpackages below into the Spring container for unified management. That's what this annotation does. So how does this annotation work? Through this @Import({Registrar.class}), here is the source code for the Registrar class.

static class Registrar implements ImportBeanDefinitionRegistrar, DeterminableImports {
        Registrar() {
        }

        public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
            AutoConfigurationPackages.register(registry, (new AutoConfigurationPackages.PackageImport(metadata)).getPackageName());
        }

        public Set<Object> determineImports(AnnotationMetadata metadata) {
            return Collections.singleton(new AutoConfigurationPackages.PackageImport(metadata));
        }
    }

_is registered through the following code.

AutoConfigurationPackages.register(registry, (new AutoConfigurationPackages.PackageImport(metadata)).getPackageName());

@Import({AutoConfigurationImportSelector.class})

What is the purpose of this note?

  1. It returns all the components that need to be imported in the project as full class names and adds them to the container.
  2. It injects a lot of automated configuration classes into the container, which is to import and configure the current project.
    Necessary components, save us from writing configuration manually to inject components.

How does it work? Open the AutoConfiguration ImportSelector class and find the following code:

List<String> configurations = this.getCandidateConfigurations(annotationMetadata, attributes);

Find the getCandidateConfigurations method, as follows:

protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
        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;
    }

Find the loadFactoryNames method, as follows:

public static List<String> loadFactoryNames(Class<?> factoryClass, @Nullable ClassLoader classLoader) {
        String factoryClassName = factoryClass.getName();
        return (List)loadSpringFactories(classLoader).getOrDefault(factoryClassName, Collections.emptyList());
    }

Find the loadSpringFactories method, which contains

Enumeration<URL> urls = classLoader != null ? classLoader.getResources("META-INF/spring.factories") : ClassLoader.getSystemResources("META-INF/spring.factories");

Here is our configuration. Where is our configuration? The following figure

@ComponentScan

The main function of this annotation is that the classes identified by the annotation are managed by the Spring container.

Topics: Spring SpringBoot xml