SpringBoot(1.5.6.RELEASE)源码解析(二)

上一篇分析了@SpringBootApplication注解,接下来从SpringApplication.run(Application.class, args);代码开始一行行DEBUG进行分析

1 @SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})
2 public class Application {
3     public static void main(String[] args) {
4         SpringApplication.run(Application.class, args);
5     }
6 }
1 public static ConfigurableApplicationContext run(Object source, String... args) {
2     return run(new Object[] { source }, args);
3 }
1 public static ConfigurableApplicationContext run(Object[] sources, String[] args) {
2     return new SpringApplication(sources).run(args);
3 }

最终会创建一个SpringApplication的对象,然后调用它的run方法

1 public SpringApplication(Object... sources) {
2     initialize(sources);
3 }

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

 1 @SuppressWarnings({ "unchecked", "rawtypes" })
 2 private void initialize(Object[] sources) {
 3     if (sources != null && sources.length > 0) {
 4         this.sources.addAll(Arrays.asList(sources));
 5     }
 6     this.webEnvironment = deduceWebEnvironment();
 7     setInitializers((Collection) getSpringFactoriesInstances(
 8             ApplicationContextInitializer.class));
 9     setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
10     this.mainApplicationClass = deduceMainApplicationClass();
11 }

首先,会把sources参数(也就是com.dylan.java.springboot.template.Application的class对象)添加到SpringApplication对象的sources属性,该属性是一个LinkedHashSet类型,然后接下来的一行调用了deduceWebEnvironment方法

1 private boolean deduceWebEnvironment() {
2     for (String className : WEB_ENVIRONMENT_CLASSES) {
3         if (!ClassUtils.isPresent(className, null)) {
4             return false;
5         }
6     }
7     return true;
8 }
1 private static final String[] WEB_ENVIRONMENT_CLASSES = { "javax.servlet.Servlet",
2             "org.springframework.web.context.ConfigurableWebApplicationContext" };

该方法会调用ClassUtils类的isPresent方法,检查classpath中是否存在javax.servlet.Servlet类和org.springframework.web.context.ConfigurableWebApplicationContext类,并赋值给SpringApplication对象的webEnvironment属性,该属性是一个boolean类型,表示启动的程序是否是一个web应用程序

接下来是第7行,主要是初始化ApplicationContextInitializer

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

接下来是第8行,主要是初始化ApplicationListener

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

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

 1 private Class<?> deduceMainApplicationClass() {
 2     try {
 3         StackTraceElement[] stackTrace = new RuntimeException().getStackTrace();
 4         for (StackTraceElement stackTraceElement : stackTrace) {
 5             if ("main".equals(stackTraceElement.getMethodName())) {
 6                 return Class.forName(stackTraceElement.getClassName());
 7             }
 8         }
 9     }
10     catch (ClassNotFoundException ex) {
11         // Swallow and continue
12     }
13     return null;
14 }

至此,SpringApplication的初始化完成

时间: 2024-08-07 08:39:19

SpringBoot(1.5.6.RELEASE)源码解析(二)的相关文章

SpringBoot(1.5.6.RELEASE)源码解析(一)

启动SpringBoot,需要在入口函数所在的类上添加@SpringBootApplication注解 1 @SpringBootApplication 2 public class Application { 3 public static void main(String[] args) { 4 SpringApplication.run(Application.class, args); 5 } 6 } 我们来看一下@SpringBootApplication注解 1 @Target(El

SpringBoot(1.5.6.RELEASE)源码解析(四)

请尊重作者劳动成果,转载请标明原文链接:http://www.cnblogs.com/dylan-java/p/7468336.html 上一篇分析了SpringApplication的run方法的一部分,接下来继续分析剩下的部分 1 public ConfigurableApplicationContext run(String... args) { 2 StopWatch stopWatch = new StopWatch(); 3 stopWatch.start(); 4 Configur

Spring 源码解析之HandlerAdapter源码解析(二)

Spring 源码解析之HandlerAdapter源码解析(二) 前言 看这篇之前需要有Spring 源码解析之HandlerMapping源码解析(一)这篇的基础,这篇主要是把请求流程中的调用controller流程单独拿出来了 解决上篇文章遗留的问题 getHandler(processedRequest) 这个方法是如何查找到对应处理的HandlerExecutionChain和HandlerMapping的,比如说静态资源的处理和请求的处理肯定是不同的HandlerMapping ge

chenglei1986/DatePicker源码解析(二)

接上一篇文章chenglei1986/DatePicker源码解析(一),我们继续将剩余的部分讲完,其实剩余的内容,就是利用Numberpicker来组成一个datePicker,代码非常的简单 为了实现自定义布局的效果,我们给Datepciker定制了一个layout,大家可以定制自己的layout <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="h

erlang下lists模块sort(排序)方法源码解析(二)

上接erlang下lists模块sort(排序)方法源码解析(一),到目前为止,list列表已经被分割成N个列表,而且每个列表的元素是有序的(从大到小) 下面我们重点来看看mergel和rmergel模块,因为我们先前主要分析的split_1_*对应的是rmergel,我们先从rmergel查看,如下 ....................................................... split_1(X, Y, [], R, Rs) -> rmergel([[Y, X

AFNetworking2.0源码解析&lt;二&gt;

本篇我们继续来看看AFNetworking的下一个模块 — AFURLRequestSerialization. AFURLRequestSerialization用于帮助构建NSURLRequest,主要做了两个事情: 1.构建普通请求:格式化请求参数,生成HTTP Header. 2.构建multipart请求. 分别看看它在这两点具体做了什么,怎么做的. 1.构建普通请求 A.格式化请求参数 一般我们请求都会按key=value的方式带上各种参数,GET方法参数直接加在URL上,POST方

volley源码解析(二)--Request&lt;T&gt;类的介绍

在上一篇文章中,我们已经提到volley的使用方式和设计的整体思路,从这篇文章开始,我就要结合具体的源码来给大家说明volley功能的具体实现. 我们第一个要介绍的类是Request<T>这个一个抽象类,我将Request称为一个请求,通过继承Request<T>来自定义request,为volley提供了更加灵活的接口. Request<T>中的泛型T,是指解析response以后的结果.在上一篇文章中我们知道,ResponseDelivery会把response分派

Mybatis 源码解析(二) - Configuration.xml解析

文章个人学习源码所得,若存在不足或者错误之处,请大家指出. 上一章中叙述了Configuration.xml流化到Mybatis内存中的过程,那么接下来肯定就是Configuration.xml文件解析操作,在Mybatis中,这个解析的操作由SqlSesssionFactoryBuilder负责.接下来我们看看SqlSessionFactoryBuilder的方法签名: SqlSessionFactoryBuilder提供了9个签名方法,其中前8个方法都是Configuration.xml的解

jQuery 源码解析(二十五) DOM操作模块 html和text方法的区别

html和text都可以获取和修改DOM节点里的内容,方法如下: html(value)     ;获取匹配元素集合中的一个元素的innerHTML内容,或者设置每个元素的innerHTML内容,                ;value可选,可以是html代码或返回html代码的函数,如果没有参数则获取匹配元素集合中第一个元素的innerHTML内容 text(text)         ;获取匹配元素集合中所有元素合并后的文本内容,或者设置每个元素的文本内容,封装了createTextNo