延伸阅读:Spring Boot启动MVC的流程

main启动

SpringApplication

  • 1 public ConfigurableApplicationContext run(String... args)

    try {
              //准备环境,并确认classpath是否拥有web环境
              ConfigurableEnvironment environment = this.prepareEnvironment(listeners, applicationArguments);
    
              //...
    
              //根据当前环境创建Spring应用上下文
              //web的则为(此处应为)o.s.b.c.e.AnnotationConfigEmbeddedWebApplicationContext
              //普通则为o.s.c.a.AnnotationConfigApplicationContext
              context = this.createApplicationContext();
    
              //...
    
              //刷新Spring应用上下文--->2
              this.refreshContext(context);
              //...
       } catch (Throwable var9) {
             //..
    }
    
  • 2 private void refreshContext(ConfigurableApplicationContext context)

private void refreshContext(ConfigurableApplicationContext context) {
        this.refresh(context);
        if (this.registerShutdownHook) {
            try {
                context.registerShutdownHook();
            } catch (AccessControlException var3) {
                ;
            }
        }

    }
  • 3protected void refresh(ApplicationContext applicationContext)
 protected void refresh(ApplicationContext applicationContext) {
    // 判断是否是AbstractApplicationContext的实例
     Assert.isInstanceOf(AbstractApplicationContext.class, applicationContext);
    // 上转,此处执行的是AnnotationConfigEmbeddedWebApplicationContext的父类的refresh
    ((AbstractApplicationContext)applicationContext).refresh();
    }

EmbeddedWebApplicationContext

  • 1 执行父类AbstractApplicationContextrefresh(),再该方法中执行到this.onRefresh();,再返回EmbeddedWebApplicationContextonRefresh()
protected void onRefresh() {
        super.onRefresh();

        try {
            //创建嵌入式servlet容器
            this.createEmbeddedServletContainer();
        } catch (Throwable var2) {
            throw new ApplicationContextException("Unable to start embedded container", var2);
        }
    }
  • 2 private void createEmbeddedServletContainer()
private void createEmbeddedServletContainer() {
        //...
        if (localContainer == null && localServletContext == null) {
            //auto-configuration 已经给你配置好了EmbeddedServletContainerFactory 
            //默认使用Tomcat,则containerFactory为TomcatEmbeddedServletContainerFactory
            EmbeddedServletContainerFactory containerFactory = this.getEmbeddedServletContainerFactory();

            //此处传入一个只有一个o.s.b.w.s.ServletContextInitializer实现的内部类
            //ServletContextInitializer是用来配置ServletContext的
            this.embeddedServletContainer = containerFactory.getEmbeddedServletContainer(new ServletContextInitializer[]{this.getSelfInitializer()});
        }
        //...
}

private ServletContextInitializer getSelfInitializer() {
        return new ServletContextInitializer() {
            public void onStartup(ServletContext servletContext) throws ServletException {
                EmbeddedWebApplicationContext.this.selfInitialize(servletContext);
            }
        };
}

TomcatEmbeddedServletContainerFactory

EmbeddedServletContainerAutoConfiguration提供实例化

  • 1 public EmbeddedServletContainer getEmbeddedServletContainer(ServletContextInitializer... initializers)
public EmbeddedServletContainer getEmbeddedServletContainer(ServletContextInitializer... initializers) {
        /*配置tomcat,容器是层次结构的,最外层是tomcat,然后是server->service->host*/
        /*Server为StandardServer Service为StandardService Host为StandardHost*/
        Tomcat tomcat = new Tomcat();
        File baseDir = this.baseDirectory != null ? this.baseDirectory : this.createTempDir("tomcat");
        tomcat.setBaseDir(baseDir.getAbsolutePath());
        Connector connector = new Connector(this.protocol);
        tomcat.getService().addConnector(connector);
        this.customizeConnector(connector);
        tomcat.setConnector(connector);
        tomcat.getHost().setAutoDeploy(false);
        this.configureEngine(tomcat.getEngine());
        Iterator var5 = this.additionalTomcatConnectors.iterator();

        while(var5.hasNext()) {
            Connector additionalConnector = (Connector)var5.next();
            tomcat.getService().addConnector(additionalConnector);
        }
        /*配置tomcat结束*/

        this.prepareContext(tomcat.getHost(), initializers);
        return this.getTomcatEmbeddedServletContainer(tomcat);
    }
  • 2 protected void prepareContext(Host host, ServletContextInitializer[] initializers)
protected void prepareContext(Host host, ServletContextInitializer[] initializers) {
        /*配置context,相当于server.xml文件中<engine>-><host>-><context>节点*/
        File docBase = this.getValidDocumentRoot();
        docBase = docBase != null ? docBase : this.createTempDir("tomcat-docbase");
        //注意 context类型为 TomcatEmbeddedContext 
        final TomcatEmbeddedContext context = new TomcatEmbeddedContext();
        context.setName(this.getContextPath());
        context.setDisplayName(this.getDisplayName());
        context.setPath(this.getContextPath());
        context.setDocBase(docBase.getAbsolutePath());
        context.addLifecycleListener(new FixContextListener());
        context.setParentClassLoader(this.resourceLoader != null ? this.resourceLoader.getClassLoader() : ClassUtils.getDefaultClassLoader());
        this.resetDefaultLocaleMapping(context);
        this.addLocaleMappings(context);

        //...
        /**配置context结束*/

        //将传入的ServletContextInitializer(EmbeddedWebApplicationContext的一个匿名内部类)与初始化TomcatEmbeddedServletContainerFactory时传入的ServletContextInitializer进行整合(ServerProperties.SessionConfiguringInitializer和InitParameterConfiguringServletContextInitializer)
        // 以上两个ServletContextInitializer来自于ServerProperties,
        // ServerProperties的bean由ServerPropertiesAutoConfiguration自动产生,由于ServerProperties实现了EmbeddedServletContainerCustomizer接口,内部的customize方法将由IoC框架执行
        ServletContextInitializer[] initializersToUse = this.mergeInitializers(initializers);
        //调用下文---->3
        this.configureContext(context, initializersToUse);
        //context配置完后,添加到host的子中
        host.addChild(context);
        this.postProcessContext(context);
}

protected final ServletContextInitializer[] mergeInitializers(ServletContextInitializer... initializers) {
        List<ServletContextInitializer> mergedInitializers = new ArrayList();
        mergedInitializers.addAll(Arrays.asList(initializers));
        mergedInitializers.addAll(this.initializers);
        return (ServletContextInitializer[])mergedInitializers.toArray(new ServletContextInitializer[mergedInitializers.size()]);
}
  • 3 protected void configureContext(Context context, ServletContextInitializer[] initializers)

    protected void configureContext(Context context, ServletContextInitializer[] initializers) {
      //创建一个TomcatStarter来包裹ServletContextInitializer
      //TomcatStarter实现了ServletContainerInitializer接口
      //以后会在其onStartup中调用ServletContextInitializer的onStartup
      //相当于容器的初始化器,会初始化ServletContext
      TomcatStarter starter = new TomcatStarter(initializers);
    
      //将容器的初始化器TomcatStarter 添加给TomcatEmbeddedContext(server.xml里的<context>,对应一个应用)
      context.addServletContainerInitializer(starter, NO_CLASSES);
    
      //做更详细的配置
    }
    
  • 4 protected TomcatEmbeddedServletContainer getTomcatEmbeddedServletContainer(Tomcat tomcat)
    执行完3后,一层层返回,最后回到1,然后调用4这个方法

protected TomcatEmbeddedServletContainer getTomcatEmbeddedServletContainer(Tomcat tomcat) {
        return new TomcatEmbeddedServletContainer(tomcat, this.getPort() >= 0);
    }

TomcatEmbeddedServletContainer

  • 1 public TomcatEmbeddedServletContainer(Tomcat tomcat, boolean autoStart) 调用构造函数
  • 2 private void initialize() throws EmbeddedServletContainerException 构造函数内,执行了此方法
private void initialize() throws EmbeddedServletContainerException {
//这一步算是完成了tomcat的初始化了
logger.info("Tomcat initialized with port(s): " + this.getPortsDescription(false));
        Object var1 = this.monitor;
        synchronized(this.monitor) {
            try {
                this.addInstanceIdToEngineName();

                try {
                    this.removeServiceConnectors();
                    //启动tomcat
                    this.tomcat.start();
                    this.rethrowDeferredStartupExceptions();
                    Context context = this.findContext();

                    try {
                        ContextBindings.bindClassLoader(context, this.getNamingToken(context), this.getClass().getClassLoader());
                    } catch (NamingException var5) {
                        ;
                    }

                    this.startDaemonAwaitThread();
                } catch (Exception var6) {
                    containerCounter.decrementAndGet();
                    throw var6;
                }
            } catch (Exception var7) {
                throw new EmbeddedServletContainerException("Unable to start embedded Tomcat", var7);
            }

        }
}

StandardServer StandardService StandardEngine

依次调用StandardServer.start()->LifecycleBase.start()->StandardServer.startInternal()
-> StandardService.start()->LifecycleBase.start()->StandardService.startInternal()
-> StandardService.start()->LifecycleBase.start()->StandardService.startInternal()
-> StandardEngine.start()->LifecycleBase.start()->StandardEngine.startInternal()->ContainerBase.startInternal()

  • 1 ContainerBase.startInternal()
protected synchronized void startInternal() throws LifecycleException {
 Container[] children = this.findChildren();
         //...

         //children 为StandardEngine的children ,当前只有一个StandardHost
         Container[] children = this.findChildren();
         List<Future<Void>> results = new ArrayList();

        //为每个host启动一个进程,使用future模型,可以回掉的
        for(int i = 0; i < children.length; ++i) {
            results.add(this.startStopExecutor.submit(new ContainerBase.StartChild(children[i])));
        }

        boolean fail = false;
        Iterator i$ = results.iterator();

        while(i$.hasNext()) {
            Future result = (Future)i$.next();

            try {
               //启动future,调用StandardHost的start方法
                result.get();
            } catch (Exception var9) {
                log.error(sm.getString("containerBase.threadedStartFailed"), var9);
                fail = true;
            }
        }

        //...
}

-> StandardHost.start()->LifecycleBase.start()->StandardHost.startInternal()->ContainerBase.startInternal()

同理启动-> TomcatEmbeddedContext .start()->LifecycleBase.start()->TomcatEmbeddedContext .startInternal()

  • 2 TomcatEmbeddedContext protected synchronized void startInternal() throws LifecycleException
protected synchronized void startInternal() throws LifecycleException {
            //...

            /*挨个启动之前放在TomcatStart里的ServletContainerInitializer*/
            Iterator i$ = this.initializers.entrySet().iterator();

            while(i$.hasNext()) {
                Entry entry = (Entry)i$.next();

                try {
                    ((ServletContainerInitializer)entry.getKey()).onStartup((Set)entry.getValue(), this.getServletContext());
                } catch (ServletException var22) {
                    log.error(sm.getString("standardContext.sciFail"), var22);
                    ok = false;
                    break;
                }
            }
            //...
}

综上完成全部内容

results matching ""

    No results matching ""