请尊重作者劳动成果,转载请标明原文链接:
上一篇分析了@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 continue12 }13 return null;14 }
至此,SpringApplication对象的初始化完成