preface

Content covers: Java, MyBatis, ZooKeeper, Dubbo, Elasticsearch, Memcached, Redis, MySQL, Spring, SpringBoot, SpringCloud, RabbitMQ, Kafka, Linux and other technology stacks.

Full version Java interview questions address: Java backend questions integration

The secret behind SpringBootApplication

The @SpringBootApplication annotation is the core annotation of SpringBoot. It is actually a composite annotation:

@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 { ... } Duplicate codeCopy the code

Although the definition uses multiple annotations to annotate the original information, there are actually only three annotations that matter:

  • @configuration (@springBootConfiguration)

  • @EnableAutoConfiguration

  • @ComponentScan

That is @SpringBootApplication = (default property)@Configuration + @EnableAutoConfiguration + @ComponentScan.

So, if we use the following SpringBoot boot class, the whole SpringBoot application will still function as the previous boot class:

@Configuration @EnableAutoConfiguration @ComponentScan public class Application { public static void main(String[] args)  { SpringApplication.run(Application.class, args); }} Copy the codeCopy the code

It’s kind of tiring to write these three at a time, so it’s a little bit easier to write at @SpringBootApplication. So let’s go through each of these annotations.

1. @ the Configuration

@Configuration is the same @Configuration that is used in the Configuration class of the Spring Ioc container in JavaConfig form. The SpringBoot community recommends using the Javaconfig-based Configuration form. The startup class labeled @Configuration is itself a Configuration class for the IoC container.

A few simple examples to review the differences between XML and Config:

(1) Expression form

The xmL-based configuration works like this:

<? The XML version = "1.0" encoding = "utf-8"? > <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd "default - lazy - init =" true "> <! -- Bean definition --> </beans> Copy codeCopy the code

Javaconfig-based configuration works like this:

@configuration public class MockConfiguration{//bean definition} copies the codeCopy the code

Any Java class definition labeled @Configuration is a JavaConfig Configuration class.

(2) Register the bean definition layer

The XML-based configuration looks like this:

<bean id="mockService" class=".. MockServiceImpl"> ... </bean> copies the codeCopy the code

The Javaconfig.based configuration looks like this:

@Configuration public class MockConfiguration{ @Bean public MockService mockService(){ return new MockServiceImpl(); }} Copy the codeCopy the code

The return value of any method labeled @bean is registered with Spring’s IoC container as a Bean definition, and the method name defaults to the id of the Bean definition.

(3) Expression of dependency injection relationship

To express bean-to-bean dependencies, in XML form we typically look like this:

<bean id="mockService" class=".. MockServiceImpl"> <propery name ="dependencyService" ref="dependencyService" /> </bean> <bean id="dependencyService" Class ="DependencyServiceImpl"></bean> Copy codeCopy the code

The Javaconfig.based configuration looks like this:

@Configuration public class MockConfiguration{ @Bean public MockService mockService(){ return new MockServiceImpl(dependencyService()); } @Bean public DependencyService dependencyService(){ return new DependencyServiceImpl(); }} Copy the codeCopy the code

If the definition of a bean depends on another bean, you can simply call the dependent bean creation method in the corresponding JavaConfig class.

@Configuration: To mention @Configuration is to mention his partner @Bean. Using these two annotations, you can create a simple Spring configuration class that can be used in place of the corresponding XML configuration file.

<beans> <bean id = "car" class="com.test.Car"> <property name="wheel" ref = "wheel"></property> </bean> <bean id = "Wheel" class="com.test. wheel" ></bean> </beans> Copy codeCopy the code

Is equivalent to:

@Configuration public class Conf { @Bean public Car car() { Car car = new Car(); car.setWheel(wheel()); return car; } @Bean public Wheel wheel() { return new Wheel(); }} Copy the codeCopy the code

The @Configuration annotation class identifies that this class can use the Spring IoC container as the source for the bean definition.

The @Bean annotation tells Spring that an annotation method with an @bean will return an object that should be registered as a Bean in the Spring application context.

2, @ ComponentScan

The @ComponentScan annotation is very important in Spring. It corresponds to elements in the XML configuration. The @ComponentScan annotation automatically scans and loads qualified components (@Component, @Repository, etc.) or bean definitions. These bean definitions are eventually loaded into the IoC container.

We can fine-grained customize the scope that @ComponentScan automatically scans through properties like basePackages. If not specified, the default Spring framework implementation scans from the package of the class in which @ComponentScan is declared.

Note: So it is best to place the boot class of SpringBoot under the root package, since basePackages are not specified by default.

3, @ EnableAutoConfiguration

I think @enableAutoConfiguration is the Annotation that’s the most important, so I’m going to leave it at the end. Do you remember the various Annotation definitions that Spring provides that start with @enable? For example, @Enablescheduling, @Enablecaching, @enablembeanexport, etc. The concept of @EnableAutoConfiguration is in fact consistent with the way of doing things. A brief summary is that with the support of @import, Collect and register bean definitions associated with specific scenarios.

@enablescheduling loads Spring scheduling-framework related bean definitions into the IoC container via @import. @enablembeanExport loads jMX-related bean definitions into the IoC container via @import. @enableAutoConfiguration loads all auto-configured bean definitions into the IoC container with the help of @import, and that’s it!

@enableAutoConfiguration will automatically configure the project based on jar dependencies in the classpath, such as: After the spring-boot-starter-web dependency is added, Tomcat and Spring MVC dependencies are automatically added, and Spring Boot automatically configures Tomcat and Spring MVC. Full version Java interview questions address: Java backend questions integration

As a composite Annotation, @enableAutoConfiguration defines the key information as follows:

@SuppressWarnings("deprecation") @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited @AutoConfigurationPackage @Import(EnableAutoConfigurationImportSelector.class) public @interface EnableAutoConfiguration {... } Duplicate codeCopy the code

One of the most critical is @ Import (EnableAutoConfigurationImportSelector. Class), with the aid of EnableAutoConfigurationImportSelector, @enableAutoConfiguration helps SpringBoot applications load all eligible @Configuration configurations into the IoC container currently created and used by SpringBoot. Like an “eight claw fish”, @enableAutoConfiguration can be automatically configured with the help of SpringFactoriesLoader, a tool class of the Spring framework.

Automatic configuration hero: SpringFactoriesLoader details

The SpringFactoriesLoader is a proprietary extension of the Spring framework that loads configurations from a specified configuration file, meta-INF/Spring.Factories.

public abstract class SpringFactoriesLoader { //... public static <T> List<T> loadFactories(Class<T> factoryClass, ClassLoader classLoader) { ... } public static List<String> loadFactoryNames(Class<? > factoryClass, ClassLoader classLoader) { .... }} Copy the codeCopy the code

Used in conjunction with @enableAutoConfiguration, it provides more of a configuration lookup feature, According to the full name of the class of the @ EnableAutoConfiguration org. Springframework. Boot. Autoconfigure. EnableAutoConfiguration as a lookup Key, Get the corresponding set of @Configuration classes.

The above excerpt from the Meta-INF/Spring.Factories configuration file in SpringBoot’s autoconfigure dependency package is a good illustration.

So the @enableAutoConfiguration magic knight becomes: Search all meta-INF/Spring. factories configuration files from the classpath, And will the org. Springframework. Boot. Autoconfigure. EnableutoConfiguration corresponding configuration items through reflection (Java Refletion) instantiated into the corresponding IoC container Configuration class in JavaConfig form annotated with @Configuration, then aggregated into one and loaded into the IoC container.


Second, explore the SpringApplication execution process in depth

The implementation of The Run method of SpringApplication is the main route of our journey, and the main process of this method can be summarized as follows:

1) If we use the static run method of SpringApplication, the method will first create an instance of the SpringApplication object, and then call the instance method. When a SpringApplication instance is initialized, it does several things ahead of time:

  • According to the characters of the classpath inside whether there is a certain kind of org. Springframework. Web. Context. ConfigurableWebApplicationContext to decide whether it should be to create a web application using ApplicationCo Ntext type.

  • Using SpringFactoriesLoader to look for in the application of the classpath and load all available ApplicationContextInitializer.

  • Use the SpringFactoriesLoader to find and load all available ApplicationListeners in your application’s classpath.

  • Infer and set the definition class for the main method.

2) After the SpringApplication instance is initialized and set, the logic of the run method is executed. First traversal perform all through SpringFactoriesLoader SpringApplicationRunListener can find and load. Call them started () method, tell these SpringApplicationRunListener, “hey, SpringBoot application to start cough up!” .

3) Create and configure the Environment to be used by the current Spring Boot application (including PropertySource and Profile to be used).

4) iterates through all SpringApplicationRunListener call environmentPrepared () method, told them: “the current SpringBoot applications use the Environment ready!” .

5) If the SpringApplication showBanner property is set to true, the banner is printed.

6) Determine what type of ApplicationContext should be created for the current SpringBoot application based on whether the applicationContextClass type has been explicitly set by the user and the inferred results of the initialization phase. Then depending on the conditions, decide whether to add ShutdownHook, decide whether to use a custom BeanNameGenerator, decide whether to use a custom ResourceLoader, and of course, most importantly, Set the previously prepared Environment to be used by the created ApplicationContext.

7) After the ApplicationContext is created, The SpringApplication will use the Spring-FactoriesLoader again, Find and load all available ApplicationContext-Initializers in your classpath, And call these ApplicationContextInitializer initialize traversal (applicationContext) method to already created good applicationContext for further processing.

8) iterates through all SpringApplicationRunListener call contextPrepared () method.

9) The most essential step is to load all the configuration obtained via @enableAutoConfiguration and other forms of IoC container configuration into the prepared ApplicationContext.

10) iterates through all SpringApplicationRunListener call contextLoaded () method.

11) Call the Refresh () method of the ApplicationContext to complete the final procedure available to the IoC container.

12) Find if CommandLineRunner is registered in the current ApplicationContext, and if so, iterate through them.

13) under normal circumstances, through implementing SpringApplicationRunListener finished () method, (if the abnormal, the whole process is still calling all SpringApplicationRunListener finished () method, Except in this case, the exception message is passed in as well.)

After removing the event notification point, the whole process is as follows:


In this paper, the debugging of an actual SpringBoot startup program as an example, referring to the main class diagram in the process, to analyze its startup logic and automatic configuration principle.

Overview:

The figure above shows the startup structure of SpringBoot. We find that the startup process is mainly divided into three parts:

  • The first part carries on the initialization module of SpringApplication, configures some basic environment variables, resources, constructors and listeners;

  • The second part realizes the application of the specific startup scheme, including the start process of the monitoring module, loading configuration environment module, and the core of the creation of context environment module;

  • The third part is the automatic configuration module, which serves as the SpringBoot automatic configuration core and will be discussed in detail in the later analysis. In the launcher below we will concatenate the main functions of the structure. Full version Java interview questions address: Java backend questions integration

Activation:

Each SpringBoot program has a main entry, which is the main method. Inside main, springApplication.run () is called to start the entire spring-Boot program. As well as the @importResource annotation (if need), @SpringBootApplication contains three annotations that do the following:

  • @enableAutoConfiguration: SpringBoot automatically configates the Spring framework based on the dependencies declared by the application.

  • @springBootConfiguration (internal @Configuration) : The annotated classes are equivalent to spring’s XML configuration file (ApplicationContext.xml), which assembs all bean transactions and provides a Spring context.

  • @ComponentScan: ComponentScan automatically finds and assembles beans. By default, SpringApplication’s Run method is scanned for booter. class files in the package path, so it is best to put the startup class in the root package path.

SpringBoot start class

First, enter the run method

The run method creates an instance of SpringApplication. Within the constructor, we can see that it calls an initialize method

The main thing here is to assign some initial values to the SpringApplication object. After the constructor completes, we return to the run method

The following key steps are implemented in this method:

1. Create the application of the listener SpringApplicationRunListeners and began to listen

ConfigurableEnvironment. If distributed through a Web container, StandardEnvironment will be loaded, which eventually inherits ConfigurableEnvironment

It can be seen that *Environment finally implements the PropertyResolver interface. When we usually obtain the value method corresponding to the specified Key in the configuration file through the Environment object, This calls the getProperty method of the propertyResolver interface

3. Configure the Environment (Environment) join the listener object (SpringApplicationRunListeners)

4. Create a run method returns the object: ConfigurableApplicationContext application configuration (context), we can have a look at the creation method:

The applicationContextClass method gets the explicitly set applicationContext, and if it doesn’t, loads the default environment configuration. Default choice AnnotationConfigApplicationContext annotation context by scanning all annotations (class to load the beans), and finally through the BeanUtils instantiation context object, and returns.

ConfigurableApplicationContext class diagram is as follows:

There are two directions of inheritance:

  • LifeCycle: LifeCycle class that defines whether or not start, stop, isRunning should run medium LifeCycle null methods

  • ApplicationContext: ApplicationContext class, which primarily inherits beanFactory(the bean’s factory class)

5. Back inside the Run method, the prepareContext method associates important components such as Listeners, Environment, applicationArguments, and Banner with context objects

The spring-boot-starter-*(mybatis, redis, etc.) method is the key to the automatic configuration of the spring-boot-starter-*(mybatis, redis, etc.). Bean instantiation and other core work.

After the configuration is complete, Springboot does some basic finishing work and returns the application context. On the basis of the above conditions, we can start the Bean instances in the container. On the basis of these conditions, we can start the Bean instances. Now that the program launched by SpringBoot has been constructed, let’s explore how automated configuration is implemented.


Automatic configuration:

In the previous startup structure diagram, we noticed that SpringBoot automatic configuration modules are called both during application initialization and during execution.

SpringBoot automatic configuration module

The main use of this configuration module is the SpringFactoriesLoader, which provides the loadFactoryNames method with factoryClass and classLoader. The spring.factories () file is loaded with the factory class name and the classLoader. The factories () file is loaded with the spring.Factories () file. The loadFactoryNames method returns the set of class names after obtaining the class names of these implementation classes. The method caller obtains these sets of class objects and constructors through reflection, and finally generates instances.

The names of the factory interface and its several implementation class interfaces

The following figure helps visualize the automatic configuration process.

Diagram of key components for SpringBoot automation configuration

The spring.factories files are stored in the meta-INF files of mybatis-spring-boot-starter, spring-boot-starter-web, etc. The SpringFactoriesLoader collects the class names in the file and returns an array of class names. The returned class names are instantiated by reflection to form a concrete factory instance that generates the bean specific to the component.

Earlier we mentioned the EnableAutoConfiguration annotation, which has the following class diagram:

Can find its finally achieved ImportSelector (selectors) and BeanClassLoaderAware (bean class loader middleware), focus on the AutoConfigurationImportSelector selectImports method.

This method is executed before SpringBoot starts the process — bean instantiation, returning a list of classes to be instantiated. We know that if we get the class information, Spring can naturally load the class into the JVM through the class loader. Now that we’ve relied on the components we need through the Spring-Boot starter dependency, we can also get the component information in the Select method. Don’t worry. Let’s move on.

Method through the method of getCandidateConfigurations annotation understands, it returns a automatic configuration of class list, method calls the loadFactoryNames method, look at the method

As you can see in the code above, the autoconfigurator loads the classes from all the spring-.Factories files in the project’s system path using the keys passed in by factoryClass.getName(). The “spring.factories” file under “mybatis-spring-boot-autoconfigure” is used

Into the org. Mybatis. Spring. The boot. Autoconfigure. MybatisAutoConfiguration, look at the main kinds of head:

Seeing that Spring’s @Configuration looks like a Spring bean annotated with annotations,

  • @ ConditionalOnClass ({SqlSessionFactory. Class, SqlSessionFactoryBean class}) : When there is a SqlSessionFactory. Class, SqlSessionFactoryBean. Class these two classes to parse MybatisAutoConfiguration configuration class, otherwise don’t resolve this a configuration class, make sence, We need MyBatis to return the session object for us, so we must have the session factory related class.

  • @condtionAlonBean (DataSource. Class) : Only DataSource that has been declared as a bean is processed.

  • ConditionalOnMissingBean(mapperFactorybean.class) ConditionalOnMissingBean(mapperFactorybean.class)

SqlSessionFactory, sqlSessionTemplate, dataSource and other mybatis components can be configured automatically. So the configuration of the above components has the same effect as the configuration of the mybatis. XML file at Spring startup.

Through the analysis we can find that as long as a classpath exist SqlSessionFactory based on SpringBoot projects. Class, SqlSessionFactoryBean. Class, and the container has registered the dataSourceBean, Mybatis can be configured automatically if you add the required dependencies to your Maven project. However, with the introduction of myBatis native dependencies, you need to modify the automatic configuration class for each feature.

Therefore, spring-boot provides us with a unified starter that can directly configure related classes and trigger the required dependencies (Mybatis) for automatic configuration as follows:

Here are all the dependencies in the POP.xml file from the source code of mybatis-spring-boot-starter:

Because of maven’s transitivity, we can rely on starter for all classes that need to be configured automatically for out-of-the-box functionality. It also shows that Springboot simplifies the large amount of XML configuration and complex dependency management brought by the Spring framework, so that developers can pay more attention to the development of business logic.

The last

Recently in view of the Internet company interview asked knowledge points, summed up the Java programmer interview involves most of the interview questions and answers to share with you, I hope to help you review before the interview and find a good job, but also save you on the Internet to search for information time to learn. Full Version of the Java InterviewJAVA backend test integration