这是最常见的也是使用最多的SpringBoot应用程序启动类,整个SpringBoot应用启动都要靠执行run方法来启动
@SpringBootApplication
public class Hibernate52Application {
public static void main(String[] args) {
SpringApplication.run(Hibernate52Application.class, args);
}
}
点进去看看
// 这是SpringApplication的run方法
public static ConfigurableApplicationContext run(Class<?> primarySource, String... args) {
return run(new Class<?>[] {
primarySource }, args);
}
// 上面的run方法实际是调用这个run方法
public static ConfigurableApplicationContext run(Class<?>[] primarySources, String[] args) {
return new SpringApplication(primarySources).run(args);
}
首先实例化SpringApplication
private ResourceLoader resourceLoader;
private WebApplicationType webApplicationType;
private List<ApplicationContextInitializer<?>> initializers;
private List<ApplicationListener<?>> listeners;
private Class<?> mainApplicationClass;
public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
// 资源加载器
this.resourceLoader = resourceLoader;
Assert.notNull(primarySources, "PrimarySources must not be null");
// JavaConfig类型的类
this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
// 根据classPath推导出web应用类型
this.webApplicationType = WebApplicationType.deduceFromClasspath();
// 初始化initializers属性
setInitializers((Collection)getSpringFactoriesInstances(ApplicationContextInitializer.class));
// 设置监听器
setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
// 推导出主应用程序类
this.mainApplicationClass = deduceMainApplicationClass();
}
SprigBootApplication 中有非常多的属性,先看这个构造方法中使用到的
- resourceLoader 资源加载器
- primarySources 在这就是 Hibernate52Application.class
- webApplicationType web应用程序类型,看代码是根据Classpath推导而来
- Initializer 元素类型为ApplicationContextInitializer的列表
- listeners 元素类型为ApplicationListener的列表
- mainApplicationClass 主应用程序类
上面的方法,先一个一个看
- deduceFormClasspath
public enum WebApplicationType {
/**
* The application should not run as a web application and should not start an
* embedded web server.
* 没有内嵌服务器
*/
NONE,
/**
* The application should run as a servlet-based web application and should start an
* embedded servlet web server.
* Servlet类型的应用
*/
SERVLET,
/**
* The application should run as a reactive web application and should start an
* embedded reactive web server.
* 响应式的应用 比如Spring-Webflux
*/
REACTIVE;
private static final String[] SERVLET_INDICATOR_CLASSES = {
"javax.servlet.Servlet",
"org.springframework.web.context.ConfigurableWebApplicationContext" };
private static final String WEBMVC_INDICATOR_CLASS = "org.springframework.web.servlet.DispatcherServlet";
private static final String WEBFLUX_INDICATOR_CLASS = "org.springframework.web.reactive.DispatcherHandler";
private static final String JERSEY_INDICATOR_CLASS = "org.glassfish.jersey.servlet.ServletContainer";
// 这个方法的作用就是判断当前的应用类型,通过使用反射在类路径下寻找是否存在对应的类,从而判断出该应用属于什么类型的应用
static WebApplicationType deduceFromClasspath() {
if (ClassUtils.isPresent(WEBFLUX_INDICATOR_CLASS, null) && !ClassUtils.isPresent(WEBMVC_INDICATOR_CLASS, null)
&& !ClassUtils.isPresent(JERSEY_INDICATOR_CLASS, null)) {
return WebApplicationType.REACTIVE;
}
for (String className : SERVLET_INDICATOR_CLASSES) {
if (!ClassUtils.isPresent(className, null)) {
return WebApplicationType.NONE;
}
}
return WebApplicationType.SERVLET;
}
}
- getSpringFactoriesInstances
private <T> Collection<T> getSpringFactoriesInstances(Class<T> type) {
return getSpringFactoriesInstances(type, new Class<?>[] {
});
}
private <T> Collection<T> getSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes, Object... args) {
// 获取类加载器
ClassLoader classLoader = getClassLoader();
// Use names and ensure unique to protect against duplicates
// 加载指定类型在"META-INF/spring.factories"对应的类名数组
Set<String> names = new LinkedHashSet<>(SpringFactoriesLoader.loadFactoryNames(type, classLoader));
// 根据类名数组创建实例
List<T> instances = createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names);
// 排序实例
AnnotationAwareOrderComparator.sort(instances);
return instances;
}
// 其中的loadFactoryNames方法并没有点进去看,其实里面的逻辑就是根据type加载在"META-INF/spring.factories"对应的类名数组
// 在META-INF/spring.factories中,以KEY-VALUE形式存储了各个类对应的实现类们
@SuppressWarnings("unchecked")
private <T> List<T> createSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes,
ClassLoader classLoader, Object