用过springboot的人应该都知道SpringApplication做boot的一个启动点,但是有多少人知道这个类做了多少事情?
我们来看下源码里面的解释:
可以通过java主程序(main)来启动spring应用,执行时需要按照以下步骤执行:
1、创建一个实例应用也就是程序;
2、注册一个资源文件来执行spring属性也就是ResourceLoader需要做的事情;
3、刷新应用程序的上下文,加载所有的单例bean;
4、触发一些需要执行的bean,指的是监听和runner;
第一种
SpringApplication.run(Application.class, args);
第二种
SpringApplication.main(args);
第三种
SpringApplication springApplication = new SpringApplication(Application.class);
springApplication.run(args);
前面两种SpringApplication的一个静态方法run,通过run构造一个SpringApplication对象,一般直接启动会直接选择第一种;第二种我觉得作用不大,因为需要构造primarySource资源,第三种一般需要改造启动类,做一些定制化代码。
/**
* Static helper that can be used to run a {@link SpringApplication} from the
* specified source using default settings.
* @param primarySource the primary source to load
* @param args the application arguments (usually passed from a Java main method)
* @return the running {@link ApplicationContext}
*/
public static ConfigurableApplicationContext run(Class> primarySource,
String... args) {
return run(new Class>[] { primarySource }, args);
}
/**
* Static helper that can be used to run a {@link SpringApplication} from the
* specified sources using default settings and user supplied arguments.
* @param primarySources the primary sources to load
* @param args the application arguments (usually passed from a Java main method)
* @return the running {@link ApplicationContext}
*/
public static ConfigurableApplicationContext run(Class>[] primarySources,
String[] args) {
return new SpringApplication(primarySources).run(args);
}
/**
* A basic main that can be used to launch an application. This method is useful when
* application sources are defined via a {@literal --spring.main.sources} command line
* argument.
*
* Most developers will want to define their own main method and call the
* {@link #run(Class, String...) run} method instead.
* @param args command line arguments
* @throws Exception if the application cannot be started
* @see SpringApplication#run(Class[], String[])
* @see SpringApplication#run(Class, String...)
*/
public static void main(String[] args) throws Exception {
SpringApplication.run(new Class>[0], args);
}
运行run方法会用两个参数primarySource、args
primarySource:主要是用于创建一个实例bean,通过这个主类加载应用的上下文,相当于所有bean的源头;
args:主要用于参数传递
1、初始化资源,启动传的值为null;
public SpringApplication(Class>... primarySources) {
this(null, primarySources);
}
2、设置bean的来源,这个是必须要有的;
this.resourceLoader = resourceLoader;
Assert.notNull(primarySources, "PrimarySources must not be null");
this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
3、推断SpringBoot的应用类型,主要分为SERVLET:基于servlet启动的应用,默认是这个;REACTIVE:基于Reactive Web启动的用于;
this.webApplicationType = deduceWebApplicationType();
4、初始化上下文初始化器;
setInitializers((Collection) getSpringFactoriesInstances(
ApplicationContextInitializer.class));
5、加载应用事件监听器
setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
6、运行SpringApplication
/**
* Create a new {@link SpringApplication} instance. The application context will load
* beans from the specified primary sources (see {@link SpringApplication class-level}
* documentation for details. The instance can be customized before calling
* {@link #run(String...)}.
* @param resourceLoader the resource loader to use
* @param primarySources the primary bean sources
* @see #run(Class, String[])
* @see #setSources(Set)
*/
@SuppressWarnings({ "unchecked", "rawtypes" })
public SpringApplication(ResourceLoader resourceLoader, Class>... primarySources) {
this.resourceLoader = resourceLoader;
Assert.notNull(primarySources, "PrimarySources must not be null");
this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
this.webApplicationType = deduceWebApplicationType();
setInitializers((Collection) getSpringFactoriesInstances(
ApplicationContextInitializer.class));
setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
this.mainApplicationClass = deduceMainApplicationClass();
}