/**
* Static helper that can be used to run a {@link SpringApplication} from the
* specified source using default settings.
* @param source the source to load
* @param args the application arguments (usually passed from a Java main method)
* @return the running {@link ApplicationContext}
*/publicstatic ConfigurableApplicationContext run(Object source, String... args){returnrun(newObject[]{ source }, args);}/**
* Static helper that can be used to run a {@link SpringApplication} from the
* specified sources using default settings and user supplied arguments.
* @param sources the sources to load
* @param args the application arguments (usually passed from a Java main method)
* @return the running {@link ApplicationContext}
*/publicstatic ConfigurableApplicationContext run(Object[] sources, String[] args){returnnewSpringApplication(sources).run(args);}
初始化
privatefinal Set<Object> sources =newLinkedHashSet<Object>();privateboolean webEnvironment;private Class<?> mainApplicationClass;privatestaticfinal String[] WEB_ENVIRONMENT_CLASSES ={"javax.servlet.Servlet","org.springframework.web.context.ConfigurableWebApplicationContext"};/**
* Create a new {@link SpringApplication} instance. The application context will load
* beans from the specified sources (see {@link SpringApplication class-level}
* documentation for details. The instance can be customized before calling
*
* 创建一个新的{@link SpringApplication}实例。
* 应用程序上下文将从指定的源加载bean(参见{@link SpringApplication class-level}文档了解详细信息)。可以在调用之前定制实例
*
* {@link #run(String...)}.
* @param sources the bean sources
* @see #run(Object, String[])
* @see #SpringApplication(ResourceLoader, Object...)
*/publicSpringApplication(Object... sources){initialize(sources);}@SuppressWarnings({"unchecked","rawtypes"})privatevoidinitialize(Object[] sources){//1,添加资源if(sources != null && sources.length >0){this.sources.addAll(Arrays.asList(sources));}//2,记录是否可以加载Servlet,ConfigurableWebApplicationContextthis.webEnvironment =deduceWebEnvironment();//加载所有的ApplicationContextInitializer子类setInitializers((Collection)getSpringFactoriesInstances(
ApplicationContextInitializer.class));//加载所有的ApplicationListener子类setListeners((Collection)getSpringFactoriesInstances(ApplicationListener.class));//获取启动类this.mainApplicationClass =deduceMainApplicationClass();}//验证Servlet,ConfigurableWebApplicationContext是否可以加载到privatebooleandeduceWebEnvironment(){for(String className : WEB_ENVIRONMENT_CLASSES){//判断改路径地址的类是否可以加载到,加载到返回trueif(!ClassUtils.isPresent(className, null)){returnfalse;}}returntrue;}//根据class,找到该接口下的所有子类//获取所有的META-INF/spring.factories文件//获取文件中配置的子类,并创建给对象private<T> Collection<?extendsT>getSpringFactoriesInstances(Class<T> type){returngetSpringFactoriesInstances(type,newClass<?>[]{});}private<T> Collection<?extendsT>getSpringFactoriesInstances(Class<T> type,
Class<?>[] parameterTypes, Object... args){
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();// Use names and ensure unique to protect against duplicates
Set<String> names =newLinkedHashSet<String>(
SpringFactoriesLoader.loadFactoryNames(type, classLoader));
List<T> instances =createSpringFactoriesInstances(type, parameterTypes,
classLoader, args, names);
AnnotationAwareOrderComparator.sort(instances);return instances;}//获取启动类private Class<?>deduceMainApplicationClass(){try{//创建一个异常,获取StackTraceElement数组,这个很有意思
StackTraceElement[] stackTrace =newRuntimeException().getStackTrace();for(StackTraceElement stackTraceElement : stackTrace){//根据main方法获取启动类if("main".equals(stackTraceElement.getMethodName())){return Class.forName(stackTraceElement.getClassName());}}}catch(ClassNotFoundException ex){// Swallow and continue}return null;}
解析
sources保存TestApplication
记录是否可以加载Servlet,ConfigurableWebApplicationContext
加载所有的ApplicationContextInitializer子类
加载所有的ApplicationListener子类
获取启动类
run
/**
* Run the Spring application, creating and refreshing a new
* 运行Spring应用程序,创建并刷新一个新的应用程序
* {@link ApplicationContext}.
* @param args the application arguments (usually passed from a Java main method)
* @return a running {@link ApplicationContext}
*/public ConfigurableApplicationContext run(String... args){//打开计时器
StopWatch stopWatch =newStopWatch();
stopWatch.start();//上下文局部变量定义
ConfigurableApplicationContext context = null;
FailureAnalyzers analyzers = null;//设置java.awt.headless的系统属性configureHeadlessProperty();//获取启动时监听器
SpringApplicationRunListeners listeners =getRunListeners(args);//启动各个监听器
listeners.starting();try{//运行参数的设置
ApplicationArguments applicationArguments =newDefaultApplicationArguments(
args);//准备环境
ConfigurableEnvironment environment =prepareEnvironment(listeners,
applicationArguments);
Banner printedBanner =printBanner(environment);//根据webEnvironment值,创建上下文或默认上下文
context =createApplicationContext();
analyzers =newFailureAnalyzers(context);//准备上下文,本文重点prepareContext(context, environment, listeners, applicationArguments,
printedBanner);//实例化单例,如果失败关闭所有单例refreshContext(context);afterRefresh(context, applicationArguments);//通知所有监听器,上下文初始化结束
listeners.finished(context, null);//关闭计时器
stopWatch.stop();//打印启动时间【Started TestApplication in 46.973 seconds (JVM running for 48.238)】if(this.logStartupInfo){newStartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch);}return context;}catch(Throwable ex){handleRunFailure(context, listeners, analyzers, ex);thrownewIllegalStateException(ex);}}