SpringBoot启动源码解析(一)

SpringBoot启动源码解析(一)

特殊说明:第一章只包含了 初始化上下文,初始化监听器列表,发布springboot启动事件 相关内容

其中一部分代码
/**
* Run the Spring application, creating and refreshing a new
* {@link ApplicationContext}.
* @param args the application arguments (usually passed from a Java main method)
* @return a running {@link ApplicationContext}
*/
public ConfigurableApplicationContext run(String... args) {
    StopWatch stopWatch = new StopWatch();
    stopWatch.start();
    DefaultBootstrapContext bootstrapContext = createBootstrapContext();
    ConfigurableApplicationContext context = null;
    configureHeadlessProperty();
    SpringApplicationRunListeners listeners = getRunListeners(args);
    listeners.starting(bootstrapContext, this.mainApplicationClass);
}

 

1、初始化一个计时器,并开始计时

StopWatch stopWatch = new StopWatch();
stopWatch.start();

其实是用来统计应用启动耗时的。

实现原理为记录下开始时间和结束时间,相减即可。

 

2、初始化启动上下文

private DefaultBootstrapContext createBootstrapContext() {
    DefaultBootstrapContext bootstrapContext = new DefaultBootstrapContext();
    this.bootstrapRegistryInitializers.forEach((initializer) -> initializer.initialize(bootstrapContext));
    return bootstrapContext;
}

new一个默认的上下文

 

3、设置该应用程序,即使没有检测到显示器,也允许其启动

configureHeadlessProperty();

private void configureHeadlessProperty() {
    System.setProperty(SYSTEM_PROPERTY_JAVA_AWT_HEADLESS,
                       System.getProperty(SYSTEM_PROPERTY_JAVA_AWT_HEADLESS, Boolean.toString(this.headless)));
}

设置了一个名为java.awt.headless的系统属性。

为true时,即使没有显示器,也可以启动。

例如linux服务器。

 

4、获取SpringApplicationRunListener的实现类

SpringApplicationRunListeners listeners = getRunListeners(args);

进入getRunListeners方法

private SpringApplicationRunListeners getRunListeners(String[] args) {
    Class<?>[] types = new Class<?>[] { SpringApplication.class, String[].class };
    return new SpringApplicationRunListeners(logger,
                                             getSpringFactoriesInstances(SpringApplicationRunListener.class, types, this, args), 
                                             this.applicationStartup);
}

①、获取了一个class数组types

其中的元素分别为:SpringApplication和String数组的class对象。在后续反射初始化对象时,types用于获取到目标的构造方法。

②、获取SpringApplicationRunListener实例对象

其中,调用了getSpringFactoriesInstances方法。该方法的目的为:获取SpringApplicationRunListener接口的所有实现类对象。

在后续的启动过程中,交由listeners发布的事件,实际上是遍历其内部管理的SpringApplicationRunListener对象列表进行发布的。

需要注意的是,通过getSpringFactoriesInstances方法获取到的SpringApplicationRunListener类型的对象有且仅有一个:EventPublishingRunListener实例对象。

③、通过获取到的SpringApplicationRunListener实例,创建一个SpringApplicationRunListeners对象并返回。

第一和第三步比较简单。

让我们关注下第二步,getSpringFactoriesInstances方法:

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

首先通过getClassLoader方法,获取到默认的类加载器,

然后通过SpringFactoriesLoader.loadFactoryNames(type, classLoader),获取SpringApplicationRunListener所有的实现类名称,

最后创建SpringApplicationRunListener接口的所有实现类对象,排序并返回。

 

 

hmoban主题是根据ripro二开的主题,极致后台体验,无插件,集成会员系统
自学咖网 » SpringBoot启动源码解析(一)