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

JAVA学习网 2017-08-31 15:01:03

上一篇分析了@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的初始化完成

阅读(791) 评论(0)