springboot 全局变量_SpringBoot源码解析之创建SpringApplication对象实例

f33b7b792dc487601c05231c1425d765.png

文章SpringBoot源码解析之SpringBoot自动装配原理中,我们分析了SpringBoot的自动装配原理以及@SpringBootApplication注解的原理,本篇文章则继续基于上篇文章中的main方法来分析SpringApplication这个类

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

点击run方法一路跟踪下来,发现首先做的是实例化SpringApplication对象实例

public static ConfigurableApplicationContext run(Class> primarySource,      String... args) {   return run(new Class>[] { primarySource }, args);}public static ConfigurableApplicationContext run(Class>[] primarySources,String[] args) {return new SpringApplication(primarySources).run(args);}//创建`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));  //1. 获取当前web环境this.webApplicationType = WebApplicationType.deduceFromClasspath();  //2. 加载所有的ApplicationContextInitializer和ApplicationListener的实现类setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));  //3. 找到入口方法main所在的类,赋值给全局变量mainApplicationClassthis.mainApplicationClass = deduceMainApplicationClass();}
  1. 首先看一下WebApplicationType.deduceFromClasspath()方法
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;}

意思就是根据当前项目中是否存在上方的几个类来推断出当前的web环境,这里因为SpringBoot默认使用的web框架是SpringMVC,所以最后返回结果为WebApplicationType.SERVLET

  1. 加载所有的ApplicationContextInitializer和ApplicationListener的实现类
private  Collection getSpringFactoriesInstances(Class type) {   return getSpringFactoriesInstances(type, new Class>[] {});}private  Collection getSpringFactoriesInstances(Class type,      Class>[] parameterTypes, Object... args) {   ClassLoader classLoader = getClassLoader();   // Use names and ensure unique to protect against duplicates   Set names = new LinkedHashSet<>(         SpringFactoriesLoader.loadFactoryNames(type, classLoader));   List instances = createSpringFactoriesInstances(type, parameterTypes,         classLoader, args, names);   AnnotationAwareOrderComparator.sort(instances);   return instances;}

可以看到主要还是用的SpringFactoriesLoader这个类去加载这两个接口的实现类,加载到类以后使用反射的方式构造出这些类的实例,然后根据这些实现类上的Order注解的值进行排序

  1. 找到入口方法main所在的类,赋值给全局变量mainApplicationClass
private Class> deduceMainApplicationClass() {   try {      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;}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值