SpringBoot framework: eternal hello world, simple view of @SpringBootApplication source code

Eternal hello world

The browser sends a hello request, the server accepts the request and processes it, and responds with the Hello World string;

  1. First create a maven project
  2. Import springboot related dependencies
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.9.RELEASE</version>
    </parent>


    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    </dependencies>
  1. Write the main program and start the spring boot application
package jane;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

/**
 * @author jane
 * @create 2020-07-31 0:59
 */

/**
 * @SpringBootApplication用来标注一个主程序类,说明这是spring boot应用
 */
@SpringBootApplication
public class Helloworld
{
    
    
    public static void main(String[] args)
    {
    
    
        SpringApplication.run(Helloworld.class, args);
    }

}

  1. Write related Controller
package jane;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
/**
 * @author jane
 * @create 2020-07-31 7:53
 */
@Controller
public class HelloController
{
    
    
    @ResponseBody
    @RequestMapping("/hello")
    public String hello()
    {
    
    
        return "hello world";
    }
}
  1. Run the main program test
  2. Simplify deployment
    <!-- 这个插件,可以将应用打包成一个可执行的jar包;-->
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

Mark this application into a jar package and execute it directly with the command of the java -jar jar file name

Exploring the hello world

POM file

  1. Parent project
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.9.RELEASE</version>
    </parent>

It's again parent project

	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-dependencies</artifactId>
		<version>1.5.9.RELEASE</version>
		<relativePath>../../spring-boot-dependencies</relativePath>
	</parent>
这个就是用来真正管理spring boot应用里面的所有依赖的版本
里面的properties标签写了很多的版本号
相当于Spring Boot的版本仲裁中心;
以后我们导入依赖默认是不需要写版本;(没有在dependencies里面管理的依赖自然需要声明版本号) 
  1. Launcher
<dependency>     
	<groupId>org.springframework.boot</groupId>     			
	<artifactId>spring‐boot‐starter‐web</artifactId> 
</dependency>

spring-boot-starter-web:
spring-boot-starter: spring-boot scene starter; helped us import the components that the web module depends on for normal operation;

Spring Boot extracts all the functional scenarios into starters (starters). All the dependencies of these starter-related scenarios need to be imported into the project. What function to use it to import what the scene launcher
specific scenes start to view the official documentation to understand, official documents

Main program

package jane;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

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

@SpringBootApplication

This is the spring boot application marking a certain class indicating that this class is the main configuration class of spring boot. Spring boot should run the main method of this class to start the spring boot application.
The content of this annotation is

@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 {
    
    

There are also many notes inside, among them

@SpringBootConfiguration

Spring Boot configuration class;
marked on a certain class, it means that this is a Spring Boot configuration class;
@SpringBootConfiguration annotation

@Target({
    
    ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Configuration
public @interface SpringBootConfiguration {
    
    
}

Among them @Configuration: is the configuration class to mark this annotation
. The configuration class here is equivalent to learning spring configuration files. The configuration class is also a component in the container,
@Component @Configuration.

@Target({
    
    ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Configuration {
    
    
    String value() default "";
}

@EnableAutoConfiguration

Turn on the automatic configuration function;
what we need to configure before, Spring Boot automatically configures for us;
@EnableAutoConfiguration tells SpringBoot to enable the automatic configuration function; so that the automatic configuration can take effect;
the content is:

@Target({
    
    ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import({
    
    EnableAutoConfigurationImportSelector.class})
public @interface EnableAutoConfiguration {
    
    
    String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";

Inside
@AutoCon Fi gurationPackage : auto-configuration package
contents inside

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

@Import(AutoConfigurationPackages.Registrar.class):
Spring’s underlying annotation @Import imports a component into the container; the imported component is determined by AutoConfigurationPackages.Registrar.class;
the content in AutoConfigurationPackages.Registrar.class is

    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));
        }
    }

From the registerBeanDefinitions method (new AutoConfigurationPackages.PackageImport(metadata)).getPackageName(), you can know that the package name of the main configuration class is obtained,
and then the registerBeanDefinitions method is to register the bean definition information, which is to scan into the package and the following components of the main configuration class container

So the function of @AutoConfigurationPackage is to
scan all the components in the package of the main configuration class (class marked by @SpringBootApplication) and all the sub-packages below to the Spring container;

@EnableAutoConfiguration also has a
@Import((EnableAutoConfigurationImportSelector.class))
First @import is to import components to the container.EnableAutoConfigurationImportSelector
: The selector of which components
to import will return all the components that need to be imported in the form of full class names, and these components will be loaded into In the container, the final effect is to import a lot of automatic configuration classes (xxxAutoConfiguration) into the container; it is to import all the components needed for this scene into the container, and configure these components;
with the automatic configuration class, we are eliminated Manually write the work of configuration injection function components, etc.

Next, let's take a look at the original code of EnableAutoConfigurationImportSelector to understand what it does.

public class EnableAutoConfigurationImportSelector extends AutoConfigurationImportSelector {
    
    
    public EnableAutoConfigurationImportSelector() {
    
    
    }

    protected boolean isEnabled(AnnotationMetadata metadata) {
    
    
        return this.getClass().equals(EnableAutoConfigurationImportSelector.class) ? (Boolean)this.getEnvironment().getProperty("spring.boot.enableautoconfiguration", Boolean.class, true) : true;
    }
}

There is no way to find its own, look for its parent class AutoConfigurationImportSelector.
Insert picture description here
Insert picture description here
Imported so many auto-configuration classes, so where do these auto-configuration classes come from?
Let us continue to the next episode to be more exciting

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

Enter getCandidateConfigurations

    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;
    }

Enter loadFactoryNames

    public static List<String> loadFactoryNames(Class<?> factoryClass, ClassLoader classLoader) {
    
    
        String factoryClassName = factoryClass.getName();

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

            while(urls.hasMoreElements()) {
    
    
                URL url = (URL)urls.nextElement();
                Properties properties = PropertiesLoaderUtils.loadProperties(new UrlResource(url));
                String factoryClassNames = properties.getProperty(factoryClassName);
                result.addAll(Arrays.asList(StringUtils.commaDelimitedListToStringArray(factoryClassNames)));
            }

            return result;
        } catch (IOException var8) {
    
    
            throw new IllegalArgumentException("Unable to load [" + factoryClass.getName() + "] factories from location [" + "META-INF/spring.factories" + "]", var8);
        }
    }

Contents in META-INF/spring.factories
Insert picture description here

When Spring Boot starts, it obtains the values ​​specified by EnableAutoConfiguration from META-INF/spring.factories under the classpath, and imports these values ​​into the container as auto-configuration classes, and the auto-configuration classes take effect and help us with auto-configuration work; Before we need to configure things by ourselves, the automatic configuration class will help us;
the overall J2EE integration solution and automatic configuration are in spring-boot-autoconfigure-1.5.9.RELEASE.jar;

Guess you like

Origin blog.csdn.net/qq_43416157/article/details/107738911