上一篇分析了@SpringBootApplication註解,接下來從SpringApplication.run(Application.class, args);代碼開始一行行DEBUG進行分析 最終會創建一個SpringApplication的對象,然後調用它的run方法 SpringAppli ...
上一篇分析了@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的初始化完成