共计 3885 个字符,预计需要花费 10 分钟才能阅读完成。
有两大步:①创立 spring 利用 ②把 spring 利用跑起来
一、创立SpringApplication
@SpringBootApplication
public class Boot09HelloTestApplication {public static void main(String[] args) {SpringApplication.run(Boot09HelloTestApplication.class, args);
}
}
step into
应用 new class 把主程序类传进来,而后调用 run 办法
public static ConfigurableApplicationContext run(Class<?> primarySource, String... args) {return run(new Class[]{primarySource}, args);
}
step into run 办法
第一步,创立 spring 利用。第二步把 spring 利用跑起来
public static ConfigurableApplicationContext run(Class<?>[] primarySources, String[] args) {return (new SpringApplication(primarySources)).run(args);
}
step into
public SpringApplication(Class... primarySources) {
// 调用本类有参结构器,传入两个参数
this((ResourceLoader)null, primarySources);
}
step into this 办法
初始化了好多属性
public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
// 第一个属性,资源加载器 resourceLoader
this.resourceLoader = resourceLoader;
// 断言你有主配置类,如果没有,则报错
Assert.notNull(primarySources, "PrimarySources must not be null");
// 把主配置类信息保存起来,this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
// 决定以后 web 利用的类型。如何决定的看上面的源码
this.webApplicationType = WebApplicationType.deduceFromClasspath();
//bootstrappers: 初始启动疏导器(我的项目一启动就要干什么)。如何获取的看上面的源码
this.bootstrappers = new ArrayList<>(getSpringFactoriesInstances(Bootstrapper.class));
// 设置初始化器。只有看到 getSpringFactoriesInstances 这个办法,都是去 META-INF/spring.factories 文件中有没有配置某个类类,它的值是什么
// 如果找到了 ApplicationContextInitializer,就会放到 List<ApplicationContextInitializer<?>> initializers 里
setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
// 设置监听器。去 spring.factories 文件中有没有配置 ApplicationListener 类,它的值是什么
setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
// 找主程序。决定哪个是主程序。如何决定的看上面的源码剖析
this.mainApplicationClass = deduceMainApplicationClass();}
如何决定以后 web 利用的类型??Servlet or 响应式编程?
static WebApplicationType deduceFromClasspath() {
// 应用 ClassUtils 工具类判断以后零碎有没有导入 org.springframework.web.reactive.DispatcherHandler 响应式编程的申请处理器
if (ClassUtils.isPresent(WEBFLUX_INDICATOR_CLASS, null) && !ClassUtils.isPresent(WEBMVC_INDICATOR_CLASS, null)
&& !ClassUtils.isPresent(JERSEY_INDICATOR_CLASS, null)) {
// 如果是响应式编程,相当于导入了 DispatcherHandler 类,就会返回它是一个响应式编程
return WebApplicationType.REACTIVE;
}
// 如果是原生的 serlvet 编程
for (String className : SERVLET_INDICATOR_CLASSES) {if (!ClassUtils.isPresent(className, null)) {return WebApplicationType.NONE;}
}
// 如果是原生的 serlvet 编程,就会返回它是一个原生的 serlvet 编程
return WebApplicationType.SERVLET;
}
如何获取初始化启动器??
private <T> Collection<T> getSpringFactoriesInstances(Class<T> type) {return getSpringFactoriesInstances(type, new Class<?>[] {});
}
// 进入 getSpringFactoriesInstances 办法
private <T> Collection<T> getSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes, Object... args) {
// 获取类的加载器
ClassLoader classLoader = getClassLoader();
//spring.factories 文件中找类型是 org.springframework.boot.Bootstrapper
Set<String> names = new LinkedHashSet<>(SpringFactoriesLoader.loadFactoryNames(type, classLoader));
// 如果没找到,即没人配置它。如果有,就会创立实例并返回
List<T> instances = createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names);
AnnotationAwareOrderComparator.sort(instances);
return instances;
}
如何决定哪个是主程序???
private Class<?> deduceMainApplicationClass() {
try {
// 去堆栈里找哪个类是有 main 办法的,有 main 办法的就是主程序,主程序有很多,只有找到第一个有 main 办法的就行了
StackTraceElement[] stackTrace = new RuntimeException().getStackTrace();
for (StackTraceElement stackTraceElement : stackTrace) {if ("main".equals(stackTraceElement.getMethodName())) {return Class.forName(stackTraceElement.getClassName());
}
}
}
catch (ClassNotFoundException ex) {// Swallow and continue}
return null;
}
创立 SpringApplication 小总结
保留一些信息。断定以后利用的类型。Servlet or 响应式编程
bootstrappers:初始启动疏导器(List<Bootstrapper>):去 spring.factories 文件中找 org.springframework.boot.Bootstrapper
找 ApplicationContextInitializer;去 spring.factories 找 ApplicationContextInitializer,保留在 List<ApplicationContextInitializer<?>> initializers
找 ApplicationListener 利用监听器。去 spring.factories 找 ApplicationListener,保留在 List<ApplicationListener<?>> listeners
简略来说,利用创立的过程,就是把一些要害的主键去 spring.factories 文件中给咱们把信息读取进去,提前保留到 springapplication 里
正文完
发表至: springboot
2022-08-08