Spring Boot启动过程源码阅读

入口

  1. 代码部分

    1
    2
    3
    4
    5
    6
    
    @SpringBootApplication
    public class WebApplication {
        public static void main(String[] args) {
            SpringApplication.run(WebApplication.class, args);
        }
    }
    
  1. 注解@SpringBootApplication

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    
    @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 {
    
    	@AliasFor(annotation = EnableAutoConfiguration.class)
    	Class<?>[] exclude() default {};
    
    	@AliasFor(annotation = EnableAutoConfiguration.class)
    	String[] excludeName() default {};
    
    	@AliasFor(annotation = ComponentScan.class, attribute = "basePackages")
    	String[] scanBasePackages() default {};
    
    	@AliasFor(annotation = ComponentScan.class, attribute = "basePackageClasses")
    	Class<?>[] scanBasePackageClasses() default {};
    
    }
    

    元注解说明

    • @Target注解类型
    • @Retention注解生命周期,包括source,class,runtime
    • @Documented注解被javadoc收录
    • @Inherited 表示被@SpringBootApplication修饰的类,其子类可以继承@SpringBootApplication注解

    框架定义的注解

    • @SpringBootConfiguration@Configuration注解,对应xml中的beans标签
    • @EnableAutoConfiguration启用SpringBoot自动配置上下文,自动扫描加载子目录下的bean
    • @ComponentScan

入口实现

  1. 构造SpringApplication代码

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    
    public static ConfigurableApplicationContext run(Class<?> primarySource,
                                                     String... args) {
        return run(new Class<?>[] { primarySource }, args);
    }
    public static ConfigurableApplicationContext run(Class<?>[] primarySources,
                                                     String[] args) {
        return new SpringApplication(primarySources).run(args);
    }
    
    //构造方法,构造SpringApplication
    @SuppressWarnings({ "unchecked", "rawtypes" })
    public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
        //设置资源加载类,null
        this.resourceLoader = resourceLoader;
        Assert.notNull(primarySources, "PrimarySources must not be null");
        //初始化主要资源集
        this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
        //判断使用的是Servlet模式,WebFlux模式或者NONE
        this.webApplicationType = WebApplicationType.deduceFromClasspath();
        //设置需要初始化组件
        setInitializers((Collection) getSpringFactoriesInstances(
            ApplicationContextInitializer.class));
        //设置监听器
        setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
        //推断主入口类
        this.mainApplicationClass = deduceMainApplicationClass();
    }
    
  1. 启动SpringApplication

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    
    public ConfigurableApplicationContext run(String... args) {
        //启动计时器
        StopWatch stopWatch = new StopWatch();
        stopWatch.start();
        ConfigurableApplicationContext context = null;
        Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
        //设置java.awt.headless参数(无界面)
        configureHeadlessProperty();
        //加载并启动监听器(初始官方默认就EventPublishListener)
        SpringApplicationRunListeners listeners = getRunListeners(args);
        listeners.starting();
        try {
            //加载启动参数
            ApplicationArguments applicationArguments = new DefaultApplicationArguments(
                args);
            //准备环境
            ConfigurableEnvironment environment = prepareEnvironment(listeners,
    applicationArguments);
            //
            configureIgnoreBeanInfo(environment);
            //打印banner图标
            Banner printedBanner = printBanner(environment);
            context = createApplicationContext();
            exceptionReporters = getSpringFactoriesInstances(
                SpringBootExceptionReporter.class,
                new Class[] { ConfigurableApplicationContext.class }, context);
            //准备上下文:
            prepareContext(context, environment, listeners, applicationArguments,
                           printedBanner);
            //刷新上下文
            refreshContext(context);
            //
            afterRefresh(context, applicationArguments);
            //计时结束
            stopWatch.stop();
            if (this.logStartupInfo) {
                new StartupInfoLogger(this.mainApplicationClass)
                    .logStarted(getApplicationLog(), stopWatch);
            }
            listeners.started(context);
            callRunners(context, applicationArguments);
        }
        catch (Throwable ex) {
            handleRunFailure(context, ex, exceptionReporters, listeners);
            throw new IllegalStateException(ex);
        }
    
        try {
            listeners.running(context);
        }
        catch (Throwable ex) {
            handleRunFailure(context, ex, exceptionReporters, null);
            throw new IllegalStateException(ex);
        }
        return context;
    }
    
  1. 准备上下文

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    
    private void prepareContext(ConfigurableApplicationContext context,
    			ConfigurableEnvironment environment, SpringApplicationRunListeners listeners,
    			ApplicationArguments applicationArguments, Banner printedBanner) {
        //设置环境参数:激活哪个profiles,加载application.properties下配置的Property
        context.setEnvironment(environment);
        postProcessApplicationContext(context);
        applyInitializers(context);
        listeners.contextPrepared(context);
        if (this.logStartupInfo) {
            logStartupInfo(context.getParent() == null);
            logStartupProfileInfo(context);
        }
        // Add boot specific singleton beans
        ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
        beanFactory.registerSingleton("springApplicationArguments", applicationArguments);
        if (printedBanner != null) {
            beanFactory.registerSingleton("springBootBanner", printedBanner);
        }
        if (beanFactory instanceof DefaultListableBeanFactory) {
            ((DefaultListableBeanFactory) beanFactory)
            .setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
        }
        // Load the sources
        Set<Object> sources = getAllSources();
        Assert.notEmpty(sources, "Sources must not be empty");
        load(context, sources.toArray(new Object[0]));
        listeners.contextLoaded(context);
    }

猜你喜欢

转载自blog.csdn.net/xiaoyeping/article/details/109989812
今日推荐