SpringBoot启动源码解析(一) ————SpringApplication 构造函数解析

**

SpringApplication 构造函数解析:

**
众所周知的springboot入口程序 main函数

public static void main(String[] args) {
        SpringApplication.run(TestspringbootApplication.class, args);
    }

springboot的启动调用SpringApplication.run的方法,再调用具体的run方法前,看一看SpringApplication怎样进行实例化的。

public static ConfigurableApplicationContext run(Class<?>[] primarySources,
   String[] args) {
  return new SpringApplication(primarySources).run(args);
 }

这里的primarySource 就是启动主类SpringbootApplication.class封装成Class[] 数组。下面具体是的SpringApplication的构造方法 :

public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
   this.resourceLoader = resourceLoader;
   Assert.notNull(primarySources, "PrimarySources must not be null");
   this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
   // 判断 web 类型
   this.webApplicationType = WebApplicationType.deduceFromClasspath();
   // 通过SpringFactory 创建初始化器 ApplicationContextInitializer
   setInitializers((Collection) getSpringFactoriesInstances(
         ApplicationContextInitializer.class));
   // 通过 SpringFactory 创建监听器 ApplicationListener
   setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
   // 获取主类
   this.mainApplicationClass = deduceMainApplicationClass();
}

可以看到主要有4个方法 ,解析每个方法是怎样实现的 :
一、WebApplicationType.deduceFromClasspath();

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;
 }

通过 ClassUtils.isPresent() 方法试加载类来进行验证判断:
1、如果这3个类都没加载 org.springframework.web.reactive.DispatcherHandler 、 org.springframework.web.servlet.DispatcherServlet 、org.glassfish.jersey.servlet.ServletContainer ,Web环境为 WebApplicationType.REACTIVE
2、 如果 javax.servlet.Servlet.org.springframework.web.context.ConfigurableWebApplicationContext 没有加载,为非Web和环境 Web
3、其余情况为 WebApplicationType.SERVLET 环境

二、getSpringFactoriesInstances(pplicationContextInitializer.class) ,以下为完整源码。

private <T> Collection<T> getSpringFactoriesInstances(Class<T> type,
      Class<?>[] parameterTypes, Object... args) {
      //  默认为当前线程类加载器  Thread.currentThread().getContextClassLoader()
   ClassLoader classLoader = getClassLoader();
   // Use names and ensure unique to protect against duplicates
   //  获取需要加载的类名
   Set<String> names = new LinkedHashSet<>(
         SpringFactoriesLoader.loadFactoryNames(type, classLoader));
   // 通过类名和class 创建实例
   List<T> instances = createSpringFactoriesInstances(type, parameterTypes,
         classLoader, args, names);
    // 排序
   AnnotationAwareOrderComparator.sort(instances);
   return instances;
}

主要有2个方法 :loadFactoryNames 和 createSpringFactoriesInstances。
loadFactoryNames方法会去加载 META-INF/spring.factories 文件,通过反射得到传入参数classType的类名去匹配应加载的类名,存入Set。

在这里插入图片描述

SpringFactoriesInstances : 通过 ClassType(必要参数) , ClassName(必要参数) 创建Instance,这方法中会根据是否为Kotlin 编译成的class文件。
猜想 : springboot 支持 Kotlin 和 java 混合编程 。

三、getSpringFactoriesInstances(ApplicationListener.class)
该方法同上,只是传入的classType参数为ApplicationListener, 将监听器实例化并存入SpringApplication。
四、deduceMainApplicationClass()

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值