SpringApplication启动过程分析(基于Javadoc进行翻译分析)

我们从代码一点一点说起,分为5部分

SpringApplication.run(Application.class, args);

        @SuppressWarnings({ "unchecked", "rawtypes" })

        public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {

                 this.resourceLoader = resourceLoader;

                 Assert.notNull(primarySources, "PrimarySources must not be null");

                 this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));

                 this.webApplicationType = deduceWebApplicationType();

                 setInitializers((Collection) getSpringFactoriesInstances(

                                  ApplicationContextInitializer.class));

                 setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));

                 this.mainApplicationClass = deduceMainApplicationClass();

        }

        它是一个静态辅助方法去基于默认的配置和从特定的源(Application.class)去运行SpringApplication。

3.1 推断web应用类型

根据给定的名字识别类,并且这个类是存在的且可被加载。若这个类或者其依赖不存在或者不能被加载,那么返回false。若spring的reactive.DispatcherHandler存在并且servlet.DispatcherServlet不存在,那么返回REACTIVE类型,否则再判断是否存在Servlet 以及spring的ConfigurableWebApplicationContext,若不都存在,那么返回NONE,以上条件都不满足返回SERVLET

        private static final String[] WEB_ENVIRONMENT_CLASSES = { "javax.servlet.Servlet",

                         "org.springframework.web.context.ConfigurableWebApplicationContext" };

private static final String REACTIVE_WEB_ENVIRONMENT_CLASS = "org.springframework."

                         + "web.reactive.DispatcherHandler";

        private static final String MVC_WEB_ENVIRONMENT_CLASS = "org.springframework."

                         + "web.servlet.DispatcherServlet";

private WebApplicationType deduceWebApplicationType() {

                 if (ClassUtils.isPresent(REACTIVE_WEB_ENVIRONMENT_CLASS, null)

                                  && !ClassUtils.isPresent(MVC_WEB_ENVIRONMENT_CLASS, null)) {

                         return WebApplicationType.REACTIVE;

                 }

                 for (String className : WEB_ENVIRONMENT_CLASSES) {

                         if (!ClassUtils.isPresent(className, null)) {

                                  return WebApplicationType.NONE;

                         }

                 }

                 return WebApplicationType.SERVLET;

        }

3.2 ApplicationContextInitializer

             它是一个回调接口,用于spring可配置的应用上下文初始化,优先于ConfigurableApplicationContext#refresh()方法执行之前。通常被用于web应用中(以编程的方式初始化应用上下文的场景)。例如激活配置或者注册属性源。

             ApplicationContextInitializer的处理器被鼓励用于推断spring的Ordered接口被实现了或者order注解是否存在,用于在实例调用之前对其进行排序。

3.3 SpringFactoriesLoader

        (1)工厂位置:可能存在多个jar file中的META-INF/spring.factories目录

        (2)遍历所有的工厂位置,放到map返回。spring可以做自动化配置,因为其已经定义好了。例如spring-boot-autoconfiguration包下的spring.factories配置了初始化器,应用监听器,自动配置导入监听器,自动配置导入过滤器,自动配置,错误分析,可提供的模板

public static final String FACTORIES_RESOURCE_LOCATION = "META-INF/spring.factories";

        private static Map<String, List<String>> loadSpringFactories(@Nullable ClassLoader classLoader) {

                 MultiValueMap<String, String> result = cache.get(classLoader);

                 if (result != null) {

                         return result;

                 }

                 try {

                         Enumeration<URL> urls = (classLoader != null ?

                                          classLoader.getResources(FACTORIES_RESOURCE_LOCATION) :

                                          ClassLoader.getSystemResources(FACTORIES_RESOURCE_LOCATION));

                         result = new LinkedMultiValueMap<>();

                         while (urls.hasMoreElements()) {

                                  URL url = urls.nextElement();

                                  UrlResource resource = new UrlResource(url);

                                  Properties properties = PropertiesLoaderUtils.loadProperties(resource);

                                  for (Map.Entry<?, ?> entry : properties.entrySet()) {

                                          List<String> factoryClassNames = Arrays.asList(

                                                          StringUtils.commaDelimitedListToStringArray((String) entry.getValue()));

                                          result.addAll((String) entry.getKey(), factoryClassNames);

                                  }

                         }

                         cache.put(classLoader, result);

                         return result;

                 }

                 catch (IOException ex) {

                         throw new IllegalArgumentException("Unable to load factories from location [" +

                                          FACTORIES_RESOURCE_LOCATION + "]", ex);

                 }

        }

3.4 mainApplicationClass

        从堆栈中遍历方法名字为main的类。

        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;

        }

 

3.5 ConfigurableApplicationContext

public interface ConfigurableApplicationContext extends ApplicationContext, Lifecycle, Closeable

 他是一个服务提供者spi接口。被大多数的应用上下文实现,提供了设施配置应用上下文,这些设施是对applicationContext的补充。提供了一下配置和生命周期方法避免他们出现在applicationContext中,仅仅被启动和关闭代码使用。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值