zoukankan      html  css  js  c++  java
  • springboot源码解析-管中窥豹系列之总体结构

    一、简介

    • Springboot源码解析是一件大工程,逐行逐句的去研究代码,会很枯燥,也不容易坚持下去。
    • 我们不追求大而全,而是试着每次去研究一个小知识点,最终聚沙成塔,这就是我们的springboot源码管中窥豹系列。

     简介

    二、框架

    我们先把springboot源码的框架了解清楚。

    1、新建一个springboot项目

    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    
    @SpringBootApplication
    public class MyprojectApplication {
    
     public static void main(String[] args) {
       SpringApplication.run(MyprojectApplication.class, args);
     }
    
    }
    
    

    2、分析源码

    相比于spring项目或者springmvc项目,springboot的入口很好找,就在main里面的run方法,我们进入run方法

    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的静态方法,新建了一个SpringApplication类,调用它的run方法,我们先看SpringApplication的构造方法,再看run方法

    public SpringApplication(Class<?>... primarySources) {
      this(null, primarySources);
    }
    
    
    @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 = WebApplicationType.deduceFromClasspath();
      setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
      setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
      this.mainApplicationClass = deduceMainApplicationClass();
    }
    

    构造方法主要做了这几件事:

    • 确定web类型:webApplicationType
    • 加载ApplicationContextInitializer
    • 加载ApplicationListener
    • 确定applicationcontext的实现类

    实现细节我们先不探讨,接着看run方法

    public ConfigurableApplicationContext run(String... args) {
      StopWatch stopWatch = new StopWatch();
      stopWatch.start();
      ConfigurableApplicationContext context = null;
      Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
      configureHeadlessProperty();
      SpringApplicationRunListeners listeners = getRunListeners(args);
      listeners.starting();
      try {
       ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
        ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);
        configureIgnoreBeanInfo(environment);
        Banner printedBanner = printBanner(environment);
        context = createApplicationContext();
        exceptionReporters = getSpringFactoriesInstances(SpringBootExceptionReporter.class,
            new Class[] { ConfigurableApplicationContext.class }, context);
        prepareContext(context, environment, listeners, applicationArguments, printedBanner);
        refreshContext(context);
        afterRefresh(context, applicationArguments);
        stopWatch.stop();
        if (this.logStartupInfo) {
            new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch);
        }
        listeners.started(context);
        callRunners(context, applicationArguments);
      }
      catch (Throwable ex) {
        handleRunFailure(context, ex, exceptionReporters, listeners);
          throw new IllegalStateException(ex);
      }
    
      try {
        listeners.running(context);
      }
      catch (Throwable ex) {
        handleRunFailure(context, ex, exceptionReporters, null);
        throw new IllegalStateException(ex);
      }
      return context;
    }
    

    run方法做了几件事:

    • stopwatch记录springboot启动耗时
    • 不同阶段触发spring的listen事件
    • 新建applicationcontext实现类
    • 启动spring:refreshContext(context)
    • 启动完成加载runner

    最重要的就是refreshContext方法,延用的springframe的fresh方法

    private void refreshContext(ConfigurableApplicationContext context) {
      refresh((ApplicationContext) context);
      if (this.registerShutdownHook) {
        try {
            context.registerShutdownHook();
        }
        catch (AccessControlException ex) {
            // Not allowed in some environments.
        }
      }
    }
    

    AbstractApplicationContext类的方法

    public void refresh() throws BeansException, IllegalStateException {
        synchronized (this.startupShutdownMonitor) {
        // Prepare this context for refreshing.
        prepareRefresh();
    
        // Tell the subclass to refresh the internal bean factory.
        ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
    
        // Prepare the bean factory for use in this context.
        prepareBeanFactory(beanFactory);
    
        try {
            // Allows post-processing of the bean factory in context subclasses.
            postProcessBeanFactory(beanFactory);
    
            // Invoke factory processors registered as beans in the context.
            invokeBeanFactoryPostProcessors(beanFactory);
    
            // Register bean processors that intercept bean creation.
            registerBeanPostProcessors(beanFactory);
    
            // Initialize message source for this context.
            initMessageSource();
    
            // Initialize event multicaster for this context.
            initApplicationEventMulticaster();
    
            // Initialize other special beans in specific context subclasses.
            onRefresh();
    
            // Check for listener beans and register them.
            registerListeners();
    
            // Instantiate all remaining (non-lazy-init) singletons.
            finishBeanFactoryInitialization(beanFactory);
    
            // Last step: publish corresponding event.
            finishRefresh();
        }
    
        catch (BeansException ex) {
            if (logger.isWarnEnabled()) {
                logger.warn("Exception encountered during context initialization - " +
                        "cancelling refresh attempt: " + ex);
            }
    
            // Destroy already created singletons to avoid dangling resources.
            destroyBeans();
    
            // Reset 'active' flag.
            cancelRefresh(ex);
    
            // Propagate exception to caller.
            throw ex;
        }
    
        finally {
            // Reset common introspection caches in Spring's core, since we
            // might not ever need metadata for singleton beans anymore...
            resetCommonCaches();
        }
        }
    }
  • 相关阅读:
    PHP设计模式——单例模式
    PHP设计模式——工厂模式
    远程备份脚本
    支持UEFI和LEGACY的多系统安装U盘
    minikube部署kubernetes学习环境
    获取kubernetes镜像
    Jenkins常用插件
    不想用ubuntu了,换个系统manjaro
    openstack stein部署手册 10. 创建实例
    openstack stein部署手册 10. horzion
  • 原文地址:https://www.cnblogs.com/ma13461749958/p/14247347.html
Copyright © 2011-2022 走看看