SpringBoot中@SpringBootApplication

@SpringBootApplication is a "three-body" structure, in fact it is a composite Annotation:

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@Configuration
@EnableAutoConfiguration
@ComponentScanpublic
@interface
SpringBootApplication{...}

Although its definition uses multiple annotations for meta-information annotation, in fact for Spring Boot applications, only three annotations are important, and the "three-body" structure actually refers to these three annotations:

  • @Configuration
  • @EnableAutoConfiguration
  • @ComponentScan


Therefore, if we use the following SpringBoot startup class, the entire SpringBoot application can still be equivalent to the previous startup class function:

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

But writing three annotations each time is obviously too cumbersome, so writing a one-stop composite annotation like @SpringBootApplication is obviously more convenient.

@Configuration Genesis

The @Configuration here is not new to us. It is  the @Configuration used by the configuration class of the Spring IoC container in the form of Java Config. Since the SpringBoot application bone is a Spring application, then naturally I need to load an IoC container. Configuration, and the SpringBoot community recommends the use of JavaConfig-based configuration form, so, obviously, after the startup class is marked with @Configuration, it is actually an IoC container configuration class!

Many SpringBoot code examples like to directly mark @Configuration or @SpringBootApplication on the startup class. For developers who are new to SpringBoot, this approach is actually not easy to understand. If we split the above SpringBoot startup class into two Independent Java classes, the whole situation is clear:

@Configuration
@EnableAutoConfiguration
@ComponentScan
public class DemoConfiguration {
    @Bean
    public Controller controller() {
        return new Controller();
    }
}

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

Therefore, the startup class DemoApplication is actually a standard Standalone type Java program main function startup class, there is nothing special. The DemoConfiguration definition marked by @Configuration is actually an ordinary IoC container configuration class in the form of JavaConfig.

The effect of @EnableAutoConfiguration

@EnableAutoConfiguration is actually not "creative", do you still remember the definition of Annotation beginning with @Enable provided by the Spring framework?

For example, @EnableScheduling, @EnableCaching, @EnableMBeanExport, etc. The concept of @EnableAutoConfiguration and the "way of doing things" are actually in the same line. To summarize briefly, with the support of @Import, the collection and registration of bean definitions related to specific scenarios are collected:

  • @EnableScheduling loads all bean definitions related to the Spring scheduling framework into the IoC container through @Import.
  • @EnableMBeanExport is to load JMX related bean definitions into IoC container through @Import.


And @EnableAutoConfiguration also uses the help of @Import to load all bean definitions that meet the conditions of automatic configuration into the IoC container, nothing more!

@EnableAutoConfiguration as a composite annotation, the key information of its own definition is as follows:

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import(EnableAutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {...}

Among them, the most critical one is @Import (EnableAutoConfigurationImportSelector.class). With the help of EnableAutoConfigurationImportSelector, @EnableAutoConfiguration can help SpringBoot applications to load all eligible @Configuration configurations into the current IoC container created and used by SpringBoot. "Clawfish" (as shown in Figure 1).

Diagram of key components where EnableAutoConfiguration is effective
Figure 1 Relationship diagram of key components where EnableAutoConfiguration is effective


With the support of an original tool class of the Spring framework: SpringFactoriesLoader, @EnableAutoConfiguration can "smartly" automatically configure the functions to be successful!

Detailed explanation of SpringFactoriesLoader

SpringFactoriesLoader belongs to an extension scheme private to the Spring framework (similar to Java's SPI scheme java.util.ServiceLoader), its main function is to load configuration from the specified configuration file META-INF / spring.factories, spring.factories is a typical java properties file, the configuration format is Key = Value, but Key and Value are full qualified names of Java type, such as:

example.MyService = example.MyServiceImpl1, example.MyServiceImpl2 and then the framework can be based on A certain type is used as a Key to find the corresponding type name list:

public abstract class SpringFactoriesLoader {
// ...
public static <T> List<T> loadFactories(Class<T> factoryClass, ClassLoader classLoader) {
...
}

public static List<String> loadFactoryNames(Class<?> factoryClass, ClassLoader classLoader) {
...
}
// ...
}

For @EnableAutoConfiguration, the purpose of SpringFactoriesLoader is slightly different, its original intention is to provide SPI extended scene, and in the scene of @EnableAutoConfiguration, it is more to provide a function of configuration search support, that is, according to @EnableAutoConfiguration The complete class name org.springframework.boot.autoconfigure.EnableAutoConfiguration is used as the search key to obtain the corresponding set of @Configuration classes:

org.springframework.boot.autoconfigure.EnableAutoConfiguration=
\org.springframework.boot.autoconfigure.admin.SpringApplicationAdmin- JmxAutoConfiguration,
\org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,
\org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration,
\org.springframework.boot.autoconfigure.MessageSourceAutoConfiguration,
\org.springframework.boot.autoconfigure.PropertyPlaceholderAuto- Configuration,
\org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration,
\org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration,
\org.springframework.boot.autoconfigure.cassandra.CassandraAuto-Configuration,
\org.springframework.boot.autoconfigure.cloud.CloudAutoConfiguration,
\org.springframework.boot.autoconfigure.context.ConfigurationProperties-AutoConfiguration,
\org.springframework.boot.autoconfigure.dao.PersistenceException-TranslationAutoConfiguration,
\org.springframework.boot.autoconfigure.data.cassandra.Cassandra-DataAutoConfiguration,
\org.springframework.boot.autoconfigure.data.cassandra.Cassandra-RepositoriesAutoConfiguration,
\...

The above is an excerpt from the META-INF / spring.factories configuration file in SpringBoot's autoconfigure dependency package, which can explain the problem well.

Therefore, the magic of @EnableAutoConfiguration automatic configuration actually becomes: search all META-INF / spring.factories configuration files from the classpath and reflect the configuration items corresponding to org.spring-framework.boot.autoconfigure.EnableAutoConfiguration through reflection ( Java Reflection) is instantiated into the corresponding IoC container configuration class in the form of JavaConfig annotated with @Configuration, and then aggregated into one and loaded into the IoC container.

Optional @ComponentScan

Why is @ComponentScan optional?

Because in principle, as the "older revolutionaries" in the Spring framework, the function of @ComponentScan is actually to automatically scan and load qualified component or bean definitions, and finally load these bean definitions into the container. Loading the bean definition into Spring's IoC container, we can manually register it individually, not necessarily through batch automatic scanning, so @ComponentScan is optional.

The same is true for Spring Boot applications, such as our startup class in this chapter:

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

If our current application does not have any bean definitions that need to be loaded into the IoC container corresponding to the current SpringBoot application through @ComponentScan, then, except for the @ComponentScan declaration, the current SpringBoot application can still run as usual with equivalent functionality.

Published 203 original articles · won praise 6 · views 4490

Guess you like

Origin blog.csdn.net/weixin_42073629/article/details/105461680