Spring boot启动原理及相关组件

优质博文:IT-BLOG-CN

一、Spring Boot应用启动

一个Spring Boot应用的启动通常如下:

@SpringBootApplication
@Slf4j
public class ApplicationMain {
    public static void main(String[] args) {
        ConfigurableApplicationContext ctx = SpringApplication.run(ApplicationMain.class, args);
    }
}

执行如上代码,Spring Boot程序启动成功。事实上启动Spring Boot应用离不开SpringApplication。
所以,我们跟随SpringApplication的脚步,开始从源码角度分析Spring Boot的初始化过程。

btw,可参看例子一节,我对Spring Boot启动的拓展点都做了demo,可参照下面源码分析进行理解。

文档有一句话说了SpringApplication做了什么(目的):

Create an appropriate ApplicationContext instance (depending on your classpath) Register a CommandLinePropertySource to expose command line arguments as Spring properties Refresh the application context, loading all singleton beans Trigger any CommandLineRunner beans

二、SpringApplication构造函数

启动代码先创建SpringApplication示例,在执行run方法:

public static ConfigurableApplicationContext run(Class<?>[] primarySources,
        String[] args) {
    return new SpringApplication(primarySources).run(args);
}

如下是SpringApplication的构造函数代码分析。

this.resourceLoader = resourceLoader;
Assert.notNull(primarySources, "PrimarySources must not be null");
this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
//通过Classloader探测不同web应用核心类是否存在,进而设置web应用类型
this.webApplicationType = WebApplicationType.deduceFromClasspath(); 
//找出所有spring.factories中声明的ApplicationContextInitializer并设置,
//ApplicationContextInitializer定义了回调接口,在refresh()前初始化调用(即在prepareContext的applyInitializers方法中调用)
setInitializers((Collection) getSpringFactoriesInstances(
ApplicationContextInitializer.class));
//找出所有spring.factories中声明的ApplicationListener(细节往后再叙),ApplicationListener继承了
//java.util.EventListener,实现了类似观察者模式的形式,通过实现ApplicationListener、SmartApplicationListener,能够监听Spring上下文的refresh、Prepared等事件或者是自定义事件
setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
//找出主启动类(有趣的是,是通过new一个runtime异常然后在异常栈里面找出来的)
this.mainApplicationClass = deduceMainApplicationClass();

在构造期间,主要做了:
1、判定应用类型,为后面创建不同类型的spring context做准备。
2、初始化ApplicationContextInitializer和ApplicationListener。
3、找出启动类。

三、run()源码解析

介绍run()方法前,先说说贯穿run方法的ApplicationRunListener,它有助于理解整个run()的运行周期。
写在这里:Spring Application事件机制

run()方法分析如下:

//java.awt.headless,是J2SE的一种模式,用于在缺失显示屏、鼠标或者键盘时的系统配置。
configureHeadlessProperty();
//将spring.factories中的SpringApplicationRunListener接口实现类拖出来,塞到SpringApplicationRunListeners(一个集合)中,统一批量执行
SpringApplicationRunListeners listeners = getRunListeners(args);
//触发runlistener的starting
listeners.starting();
try {
   ApplicationArguments applicationArguments = new DefaultApplicationArguments(
         args);
   ConfigurableEnvironment environment = prepareEnvironment(listeners,
         applicationArguments);
   //spring.beaninfo.ignore如果没有设置值,则把它设为true,具体情况具体设置,
   //如果没用的话,把它设为true可以ignore掉classloader对于不存在的BeanInfo的扫描,提高性能。
   configureIgnoreBeanInfo(environment);
   //banner打印。自定义banner挺好玩的
   Banner printedBanner = printBanner(environment);
   //根据webApplicationType(一开始推断的应用类型)去新建applicationContext
   context = createApplicationContext();
   //获取SpringBootExceptionReporter,回调接口类,提供启动时的异常报告
   exceptionReporters = getSpringFactoriesInstances(
         SpringBootExceptionReporter.class,
         new Class[] { ConfigurableApplicationContext.class }, context);
   //下面会说
   prepareContext(context, environment, listeners, applicationArguments,
         printedBanner);
   refreshContext(context);
   //do nothing
   afterRefresh(context, applicationArguments);
   //计时停止
   stopWatch.stop();
   //打日志
   if (this.logStartupInfo) {
      new StartupInfoLogger(this.mainApplicationClass)
            .logStarted(getApplicationLog(), stopWatch);
   }
   //启动
   listeners.started(context);
   //找出context的ApplicationRunner和CommandL
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值