当前位置: 首页 > news >正文

佛山网站搭建公司哪家好dz论坛做视频网站教程

佛山网站搭建公司哪家好,dz论坛做视频网站教程,江苏宏远建设集团网站,新郑网络推广SpringBoot启动流程分析之创建SpringApplication对象(一) 目录: 文章目录 SpringBoot启动流程分析之创建SpringApplication对象(一)1、SpringApplication的构造方法1.1、推断应用程序类型1.2、设置Initializers1.3、设置Listener1.4、推断main方法所在类 流程分析…

SpringBoot启动流程分析之创建SpringApplication对象(一)

目录:

文章目录

      • SpringBoot启动流程分析之创建SpringApplication对象(一)
          • 1、SpringApplication的构造方法
            • 1.1、推断应用程序类型
            • 1.2、设置Initializers
            • 1.3、设置Listener
            • 1.4、推断main方法所在类

流程分析

1、SpringApplication的构造方法

来看一下在SpringApplication对象的构造方法中都做了哪些事。

public SpringApplication(Class<?>... primarySources) {this(null, primarySources);
}@SuppressWarnings({ "unchecked", "rawtypes" })
public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {this.resourceLoader = resourceLoader;//判断primarySources不能为空Assert.notNull(primarySources, "PrimarySources must not be null");//将primarySources放入SpringApplication的全局变量primarySources,Set集合中this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));//从类路径中推断应用程序类型放到SpringApplication的全局变量webApplicationType this.webApplicationType = WebApplicationType.deduceFromClasspath();//从META-INF/spring.factories文件中获取ApplicationContextInitializer接口的实现类并利用反射创建对象返回放入SpringApplication的全局变量initializers,List集合中setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));//同上,也是从META-INF/spring.factories文件中获取ApplicationListener接口的实现类并利用反射创建对象返回放入SpringApplication的全局变量listeners,List集合中setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));//通过获取当前调用栈,找到入口方法main所在的类,放入SpringApplication的全局变量mainApplicationClass this.mainApplicationClass = deduceMainApplicationClass();
}
1.1、推断应用程序类型
private static final String[] SERVLET_INDICATOR_CLASSES = { "javax.servlet.Servlet","org.springframework.web.context.ConfigurableWebApplicationContext" };private static final String WEBFLUX_INDICATOR_CLASS = "org."+ "springframework.web.reactive.DispatcherHandler";private static final String WEBMVC_INDICATOR_CLASS = "org.springframework."+ "web.servlet.DispatcherServlet";private static final String JERSEY_INDICATOR_CLASS = "org.glassfish.jersey.servlet.ServletContainer";static WebApplicationType deduceFromClasspath() {//ClassUtils.isPresent()从默认classloader中判断是否存在对应的类型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;
}

推断逻辑是:

先是判断默认的classloader中是否存在org.springframework.web.reactive.DispatcherHandler、且不存在org.springframework.web.servlet.DispatcherServlet、org.glassfish.jersey.servlet.ServletContainer,如果为true返回WebApplicationType.REACTIVE;

然后循环String数组,判断如果默认的classloader中是否不存在javax.servlet.Servlet和org.springframework.web.context.ConfigurableWebApplicationContext,如果不存在,则认为不是web应用程序,返回WebApplicationType.NONE;

最后是返回WebApplicationType.SERVLET。

三种返回类型的解释如下:

    1、WebApplicationType.NONE:不是web应用程序2、WebApplicationType.SERVLET:基于servlet的Web应用程序运行3、WebApplicationType.REACTIVE:响应式的web应用程序
1.2、设置Initializers

传入参数是class类型即ApplicationContextInitializer.class,最终调用方法是getSpringFactoriesInstances,注意第二个参数,传的是一个空的Class数组,则加载所有的配置的类,方便后续给定限定类型的时候无需再次加载,直接从cache中读取。

SpringFactoriesLoader.loadFactoryNames(Class<?> factoryClass, @Nullable ClassLoader classLoader):这个方法,其作用是使用给定的类加载器从“META-INF/spring.factories”加载给定类型的工厂实现的完全限定类名,即得到所有ApplicationContextInitializer接口实现类的完全限定类名,去重。

setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));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//得到所有ApplicationContextInitializer接口的实现类Set<String> names = new LinkedHashSet<>(SpringFactoriesLoader.loadFactoryNames(type, classLoader));//创建所有ApplicationContextInitializer接口实现类的实例List<T> instances = createSpringFactoriesInstances(type, parameterTypes,classLoader, args, names);//根据order排序AnnotationAwareOrderComparator.sort(instances);return instances;
}

随后当做参数传递到createSpringFactoriesInstances方法中,这个方法主要作用就是根据传入的type类型,parameterTypes参数类型(空Class数组)以及得到的完全限定类名集合创建对象实例,其中getDeclaredConstructor方法作用是得到指定参数类型的构造方法,parameterTypes为空数组即的得到的就是默认构造方法。构造方法基本都是空的,所以无需关心创建Initializers实例的时候在构造方法中执行了什么操作。这些对象的initialize方法会在后面的run方法中被调用。

@SuppressWarnings("unchecked")
private <T> List<T> createSpringFactoriesInstances(Class<T> type,Class<?>[] parameterTypes, ClassLoader classLoader, Object[] args,Set<String> names) {//new 一个跟检索出来的接口实现类相同size的ListList<T> instances = new ArrayList<>(names.size());for (String name : names) {try {//通过类加载器加载类Class<?> instanceClass = ClassUtils.forName(name, classLoader);//判断是否为ApplicationContextInitializer接口的实现类Assert.isAssignable(type, instanceClass);//得到指定参数类型的构造方法Constructor<?> constructor = instanceClass.getDeclaredConstructor(parameterTypes);//创建对象T instance = (T) BeanUtils.instantiateClass(constructor, args);//放到List中,返回instances.add(instance);}catch (Throwable ex) {throw new IllegalArgumentException("Cannot instantiate " + type + " : " + name, ex);}}return instances;
}

spring.factories文件内容中Initializers如下。

在这里插入图片描述
在这里插入图片描述

1.3、设置Listener

这一步跟上面设置Initializers执行的操作是一样的。spring.factories文件内容中Listener如下。
在这里插入图片描述

整理一下Listener对应的Event

监听器事件类型
BackgroundPreinitializerApplicationStartingEvent、ApplicationEnvironmentPreparedEvent、ApplicationPreparedEvent、ApplicationStartedEvent、ApplicationReadyEvent、ApplicationFailedEvent、ApplicationContextInitializedEvent
ClearCachesApplicationListenerContextRefreshedEvent
ParentContextCloserApplicationListenerParentContextAvailableEvent
FileEncodingApplicationListenerApplicationEnvironmentPreparedEvent
AnsiOutputApplicationListenerApplicationEnvironmentPreparedEvent
ConfigFileApplicationListenerApplicationEnvironmentPreparedEvent、ApplicationPreparedEvent
DelegatingApplicationListenerApplicationEnvironmentPreparedEvent
ClasspathLoggingApplicationListenerApplicationEnvironmentPreparedEvent、ApplicationFailedEvent
LoggingApplicationListenerApplicationStartingEvent、ApplicationEnvironmentPreparedEvent、ApplicationPreparedEvent、ContextClosedEvent、ApplicationFailedEvent
LiquibaseServiceLocatorApplicationListenerApplicationStartingEvent
1.4、推断main方法所在类

StackTraceElement数组包含了StackTrace(堆栈轨迹)的内容,通过遍历它可以得到当前方法以及其定义类、调用行数等信息。
在这里插入图片描述

private Class<?> deduceMainApplicationClass() {try {//获取StackTraceElement数组,也就是这个栈的信息。StackTraceElement[] stackTrace = new RuntimeException().getStackTrace();for (StackTraceElement stackTraceElement : stackTrace) {if ("main".equals(stackTraceElement.getMethodName())) {//stackTraceElement.getClassName(),得到定义类,即main方法所在类return Class.forName(stackTraceElement.getClassName());}}}catch (ClassNotFoundException ex) {// Swallow and continue}return null;
}

SpringApplication对象的创建过程就完成了。

Springboot 启动还可以使用流式API SpringApplicationBuilder的方式启动:

@SpringBootApplication
public class RegisterApplication {public static void main(String[] args) {new SpringApplicationBuilder(RegisterApplication.class)// 设置当前应用类型.web(WebApplicationType.SERVLET)// 设置 banner 横幅打印方式、有关闭、日志、控制台.bannerMode(Banner.Mode.OFF)// 设置自定义的 banner.banner()// 追加自定义的 initializer 到集合中 .initializers()// 追加自定义的 listeners 到集合中.listeners().run(args);}
}
http://www.yayakq.cn/news/875833/

相关文章:

  • 网络公司给我做网站我有没有源代码版权吗?家用电脑做网站
  • asp网站关键字php网站开发预算文档
  • 江苏有什么网站找工程建设人员php网站建设案例教程
  • 唐山网站建设哪家好wordpress网站关键字
  • 怎么建设影视卡网站制作网站的公司电话号码
  • 合肥专门做网站北京网站建设模板
  • 做网站经常用的字体有哪些四川佳和建设工程网站
  • 网站建设服务方案ppt网店推广发展趋势
  • 做建材去什么网站公司的网站
  • 深圳网站优化指导高端品牌手表
  • 云平台建设网站莱芜百度网站建设
  • 做外贸做的很好的网站农村建设自己的网站
  • 阿里云的网站模版好吗做网站最重要的是什么
  • 关于网站建设资金的报告昆明营销型网站建设公司
  • 网站摄影设计中国500强公司有哪些
  • seo网站推广的主要目的不包括百度客户端在哪里打开
  • 青岛建站通工程装修
  • 商户如何做h5商城网站是什么意思合肥中小企业网站制作
  • 怎样做一个企业的网站建站qq空间怎么做网站
  • 做团购网站视频佛山大型网站建设
  • 庆阳网站设计厂家网站关键词设置多少个
  • 门户网站建设议题汇报材料移动开发的现状和前景
  • 深圳做网上商城网站北京室内设计公司
  • 手机网站模板国外h5网站模板
  • 手把手教你实现电商网站开发seo工作职位
  • 网站开发 html长春建站程序
  • 做网站项目所需资源重庆网站建设重庆
  • 廊坊网站关键词推广小型企业网络设计方案报告
  • 装修网站建设网seo关键字优化教程
  • 服装服饰设计网站网站维护年费