spring boot 源码分析(一)

1、spring boot 入口类

package com.vesus.springboothelloworld;

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

@SpringBootApplication
public class SpringbootHelloworldApplication {

    public static void main(String[] args) {

        SpringApplication.run(SpringbootHelloworldApplication.class, args);
    }
}

2、查看注解@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 {
    ...
}

去掉元注解,剩下三个注解@SpringBootConfiguration,@EnableAutoConfiguration,@ComponentScan下面我们进入到SpringBootConfiguration类。

2.1、查看@SpringBootConfiguration注解

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

可以看到这个注解实际上和@Configuration有相同的作用.

2.2、@ComponentScan

顾名思义,这个注解完成的是自动扫描的功能,相当于Spring XML配置文件中的,默认扫描@ComponentScan注解所在类的同级类和同级目录下的所有类.

<context:component-scan>

2.3、@EnableAutoConfiguration

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

    Class<?>[] exclude() default {};

    String[] excludeName() default {};
}
  1. 入口方法

3.1 SpringApplication的实例化

SpringApplication.run(SpringbootHelloworldApplication.class, args);

相应实现:

//实现方法
public static ConfigurableApplicationContext run(Object source, String... args) {
    return run(new Object[]{source}, args);
}
//重载方法
public static ConfigurableApplicationContext run(Object[] sources, String[] args) {
    return (new SpringApplication(sources)).run(args);
}

它实际上会构造一个SpringApplication的实例(new SpringApplication),然后运行它的run方法:

public SpringApplication(Object... sources) {
    //调用初始化方法
    initialize(sources);
}

SpringApplication的构造函数会调用initialize方法进行初始化

private void initialize(Object[] sources) {
    //判断参数是否存在,存在添加至sources中,该属性是一个LinkedHashSet类型
    if (sources != null && sources.length > 0) {
        this.sources.addAll(Arrays.asList(sources));
    }
    //判断是否为web程序,主要判断类中是否包含(“javax.servlet.Servlet",
            "org.springframework.web.context.ConfigurableWebApplicationContext)这两个类
    this.webEnvironment = deduceWebEnvironment();
    setInitializers((Collection) getSpringFactoriesInstances(
    ApplicationContextInitializer.class));
    setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
    this.mainApplicationClass = deduceMainApplicationClass();
}

1、首先,会把sources参数添加到SpringApplication对象的sources属性,该属性是一个LinkedHashSet类型

private final Set<Object> sources = new LinkedHashSet<Object>();

接下来的调用了deduceWebEnvironment方法,判断是否为web程序,主要判断类中是否包含(“javax.servlet.Servlet”,

        "org.springframework.web.context.ConfigurableWebApplicationContext)这两个类

    private boolean deduceWebEnvironment() {
        for (String className : WEB_ENVIRONMENT_CLASSES) {
            if (!ClassUtils.isPresent(className, null)) {
                return false;
            }
        }
        return true;
    }

private static final String[] WEB_ENVIRONMENT_CLASSES = { "javax.servlet.Servlet",
            "org.springframework.web.context.ConfigurableWebApplicationContext" };

2、接下来初始化ApplicationContextInitializer

在classpath下的JAR文件中包含的/META/spring.factories文件里找到对应的属性,然后实例化并排序,设置到SpringApplication对象的initializers属性,该属性是一个ArrayList类型

private <T> Collection<? extends T> getSpringFactoriesInstances(Class<T> type,
            Class<?>[] parameterTypes, Object... args) {
        ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
        // 在classpath下的JAR文件中包含的/META/spring.factories文件里找到对应的属性
        Set<String> names = new LinkedHashSet<String>(
                SpringFactoriesLoader.loadFactoryNames(type, classLoader));
        List<T> instances = createSpringFactoriesInstances(type, parameterTypes,
                classLoader, args, names);
        //实例化并排序,设置到SpringApplication对象的initializers属性
        AnnotationAwareOrderComparator.sort(instances);
        return instances;
    }

取出的属性值为:

0 = "org.springframework.boot.context.ConfigurationWarningsApplicationContextInitializer"
1 = "org.springframework.boot.context.ContextIdApplicationContextInitializer"
2 = "org.springframework.boot.context.config.DelegatingApplicationContextInitializer"
3 = "org.springframework.boot.context.embedded.ServerPortInfoApplicationContextInitializer"
4 = "org.springframework.boot.autoconfigure.SharedMetadataReaderFactoryContextInitializer"
5 = "org.springframework.boot.autoconfigure.logging.AutoConfigurationReportLoggingInitializer"

3、初始化监听器ApplicationListener

在classpath下的JAR文件中包含的/META/spring.factories文件里找到org.springframework.context.ApplicationListener对应的属性,然后实例化并排序,设置到SpringApplication对象的listeners属性,该属性是一个ArrayList类型

private <T> Collection<? extends T> getSpringFactoriesInstances(Class<T> type,
            Class<?>[] parameterTypes, Object... args) {
        ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
        // Use names and ensure unique to protect against duplicates
        Set<String> names = new LinkedHashSet<String>(
                SpringFactoriesLoader.loadFactoryNames(type, classLoader));
        List<T> instances = createSpringFactoriesInstances(type, parameterTypes,
                classLoader, args, names);
        AnnotationAwareOrderComparator.sort(instances);
        return instances;
    }

取出的属性值为:

0 = "org.springframework.boot.ClearCachesApplicationListener"
1 = "org.springframework.boot.builder.ParentContextCloserApplicationListener"
2 = "org.springframework.boot.context.FileEncodingApplicationListener"
3 = "org.springframework.boot.context.config.AnsiOutputApplicationListener"
4 = "org.springframework.boot.context.config.ConfigFileApplicationListener"
5 = "org.springframework.boot.context.config.DelegatingApplicationListener"
6 = "org.springframework.boot.liquibase.LiquibaseServiceLocatorApplicationListener"
7 = "org.springframework.boot.logging.ClasspathLoggingApplicationListener"
8 = "org.springframework.boot.logging.LoggingApplicationListener"
9 = "org.springframework.boot.autoconfigure.BackgroundPreinitializer"

4、最后调用deduceMainApplicationClass方法找到main函数所在的类,实现的方式是获取当前方法调用栈,找到main函数的类,并设置到SpringApplication对象的mainApplicationClass属性,该属性是一个Class类型

private Class<?> deduceMainApplicationClass() {
        try {
            StackTraceElement[] stackTrace = new RuntimeException().getStackTrace();
            for (StackTraceElement stackTraceElement : stackTrace) {
                if ("main".equals(stackTraceElement.getMethodName())) {
                    return Class.forName(stackTraceElement.getClassName());
                }
            }
        }
        catch (ClassNotFoundException ex) {
            // Swallow and continue
        }
        return null;
    }
    原文作者:Spring Boot
    原文地址: https://blog.csdn.net/liuweilong07/article/details/80293090
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞