Spring Boot的初始化时从一个main方法开始,进入调用到SpringApplication的内部去实现java
首先调用的是web
进入这个类的内部就是spring
继续tomcat
核心就是从这个new方法开始,run(args)开始执行各类初始化环境的操做springboot
首先咱们来看这个构造方法app
这个方法调用的是initialize方法区初始化各类须要的条件环境less
private void initialize(Object[] sources) { if (sources != null && sources.length > 0) { this.sources.addAll(Arrays.asList(sources)); } //经过判断是否能加载到Servlate跟ConfigurableWebApplicationContext这个类去判读是否为web环境 this.webEnvironment = deduceWebEnvironment(); //读取spring.factories文件中的org.springframework.context.ApplicationContextInitializer对应的各类类名,而后加载内存建立好,为了下面使用 setInitializers((Collection) getSpringFactoriesInstances( ApplicationContextInitializer.class)); //读取spring.factories文件中的org.springframework.context.ApplicationListener对应的各类类名,而后加载内存建立好,为了下面使用 setListeners((Collection)getSpringFactoriesInstances(ApplicationListener.class)); //肯定main方法所在的类 this.mainApplicationClass = deduceMainApplicationClass(); }
以一个方法为例子this
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 //这是根据spring.facotories文件获得的value都是一些SpringApplicationRunListener的实现类的全类名称 Set<String> names = new LinkedHashSet<String>( SpringFactoriesLoader.loadFactoryNames(type, classLoader)); //加载到内存并初始化实例 List<T> instances = createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names); //根据实例的名称排序 AnnotationAwareOrderComparator.sort(instances); return instances; }
值得小注意的是:Spring使用的是线程上下文加载器,去加载的本身的各个模块的jar中的类,由于为了确保加载器必定是当前容器的加载器,才能够加在到这些Class文件的,好比当前的环境是web环境,并且是tomcat的容器,因此这些jar文件是经过的tomcat的的类加载去加载的,而默认的线程上下文加载就是自定义的tomcat容器加载器,因此须要这样去加载Class,其实就是经过类加载器能够更换咱们想要的加载器spa
下面就是简单的根据ClassLoader还有Class类型去加载类文件到内存,而后实例化的过程,而后返回这些实例对象线程
当须要的ApplicationContextInitializer、ApplicationListener实现类加载完成后,都会保存到SpringApplication这个类的对应的Map中
//保存ApplicationContextInitializer实现类的实例对象 public void setInitializers( Collection<? extends ApplicationContextInitializer<?>> initializers) { this.initializers = new ArrayList<ApplicationContextInitializer<?>>(); this.initializers.addAll(initializers); } //保存ApplicationListener实现类的的实例对象 public void setListeners(Collection<? extends ApplicationListener<?>> listeners) { this.listeners = new ArrayList<ApplicationListener<?>>(); this.listeners.addAll(listeners); }
大概加载流程以下
至此springboot创造一个SpringApplication这个类,准备了实例化各类配置参数类,而后进入到真正的建立SpringContext整个环境的入口
public ConfigurableApplicationContext run(String... args) { //建立一个监听类StopWacht,记录启动的时间,加载类等信息输出到log StopWatch stopWatch = new StopWatch(); stopWatch.start(); ConfigurableApplicationContext context = null; FailureAnalyzers analyzers = null; //用来设置java.awt.headless 属性是true 仍是false,是J2SE的一种模式用于在缺乏显示屏、键盘 //或者鼠标时的系统配置 configureHeadlessProperty(); //读取spring.factory中配置初始化EventPublishingRunListener这个类 SpringApplicationRunListeners listeners = getRunListeners(args); //发送启动事件到对应的各个监听器中 listeners.starting(); try { ApplicationArguments applicationArguments = new DefaultApplicationArguments( args); ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments); Banner printedBanner = printBanner(environment); context = createApplicationContext(); analyzers = new FailureAnalyzers(context); prepareContext(context, environment, listeners, applicationArguments, printedBanner); refreshContext(context); afterRefresh(context, applicationArguments); listeners.finished(context, null); stopWatch.stop(); if (this.logStartupInfo) { new StartupInfoLogger(this.mainApplicationClass) .logStarted(getApplicationLog(), stopWatch); } return context; } catch (Throwable ex) { handleRunFailure(context, listeners, analyzers, ex); throw new IllegalStateException(ex); } }