springboot啟動(dòng)解析八

本章節(jié)繼續(xù)分析run方法的第15行代碼:

public ConfigurableApplicationContext run(String... args) {
        1.StopWatch stopWatch = new StopWatch();
        2.stopWatch.start();
        3.ConfigurableApplicationContext context = null;
        4.Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
        5.configureHeadlessProperty();
        6.SpringApplicationRunListeners listeners = getRunListeners(args);
        7.listeners.starting();
        try {
        8.  ApplicationArguments applicationArguments = new DefaultApplicationArguments(
                    args);
        9.  ConfigurableEnvironment environment = prepareEnvironment(listeners,
                    applicationArguments);
        10. configureIgnoreBeanInfo(environment);
        11. Banner printedBanner = printBanner(environment);
        12. context = createApplicationContext();
        13. exceptionReporters = getSpringFactoriesInstances(
                SpringBootExceptionReporter.class,
                    new Class[] { ConfigurableApplicationContext.class }, context);
        14.     prepareContext(context, environment, listeners, applicationArguments,
                    printedBanner);
        15. refreshContext(context);
        16. afterRefresh(context, applicationArguments);
        17. stopWatch.stop();
        18. if (this.logStartupInfo) {
        19.     new StartupInfoLogger(this.mainApplicationClass)
                        .logStarted(getApplicationLog(), stopWatch);
            }
        20. listeners.started(context);
        21. callRunners(context, applicationArguments);
        }
        catch (Throwable ex) {
        22. handleRunFailure(context, ex, exceptionReporters, listeners);
            throw new IllegalStateException(ex);
        }

        try {
        23. listeners.running(context);
        }
        catch (Throwable ex) {
        24. handleRunFailure(context, ex, exceptionReporters, null);
            throw new IllegalStateException(ex);
        }
        return context;
    }
  • 其中第15行的代碼如下:
    @Override
    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();
            }
        }
    }

本章節(jié)主要分析:registerBeanPostProcessors,initMessageSource,initApplicationEventMulticaster,onRefresh,registerListeners,finishBeanFactoryInitialization,finishRefresh,destroyBeans,cancelRefresh,resetCommonCaches

registerBeanPostProcessors

  • 具體代碼如下:registerBeanPostProcessors 本行代碼就是注冊(cè)BeanPostProcessors
    具體代碼如下:
public static void registerBeanPostProcessors(
            ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {

        String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);

        // Register BeanPostProcessorChecker that logs an info message when
        // a bean is created during BeanPostProcessor instantiation, i.e. when
        // a bean is not eligible for getting processed by all BeanPostProcessors.
        int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;
        beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));

        // Separate between BeanPostProcessors that implement PriorityOrdered,
        // Ordered, and the rest.
        List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
        List<BeanPostProcessor> internalPostProcessors = new ArrayList<>();
        List<String> orderedPostProcessorNames = new ArrayList<>();
        List<String> nonOrderedPostProcessorNames = new ArrayList<>();
        for (String ppName : postProcessorNames) {
            if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
                BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
                priorityOrderedPostProcessors.add(pp);
                if (pp instanceof MergedBeanDefinitionPostProcessor) {
                    internalPostProcessors.add(pp);
                }
            }
            else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
                orderedPostProcessorNames.add(ppName);
            }
            else {
                nonOrderedPostProcessorNames.add(ppName);
            }
        }

        // First, register the BeanPostProcessors that implement PriorityOrdered.
        sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
        registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);

        // Next, register the BeanPostProcessors that implement Ordered.
        List<BeanPostProcessor> orderedPostProcessors = new ArrayList<>();
        for (String ppName : orderedPostProcessorNames) {
            BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
            orderedPostProcessors.add(pp);
            if (pp instanceof MergedBeanDefinitionPostProcessor) {
                internalPostProcessors.add(pp);
            }
        }
        sortPostProcessors(orderedPostProcessors, beanFactory);
        registerBeanPostProcessors(beanFactory, orderedPostProcessors);

        // Now, register all regular BeanPostProcessors.
        List<BeanPostProcessor> nonOrderedPostProcessors = new ArrayList<>();
        for (String ppName : nonOrderedPostProcessorNames) {
            BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
            nonOrderedPostProcessors.add(pp);
            if (pp instanceof MergedBeanDefinitionPostProcessor) {
                internalPostProcessors.add(pp);
            }
        }
        registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors);

        // Finally, re-register all internal BeanPostProcessors.
        sortPostProcessors(internalPostProcessors, beanFactory);
        registerBeanPostProcessors(beanFactory, internalPostProcessors);

        // Re-register post-processor for detecting inner beans as ApplicationListeners,
        // moving it to the end of the processor chain (for picking up proxies etc).
        beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));
    }

先加個(gè)BeanPostProcessorChecker,會(huì)在beanPostBean創(chuàng)建bean的時(shí)候 打印信息或者打印不合格的bean

  • 所以通過以上可知道 beanDeifion在BeanFactoryPostProcessor確定
  • beanPostProcessor確定最終的bean(因?yàn)閎ean在初始化結(jié)束前后可以獲取修改bean)
  • 查找 四種類型的beanPostProcessor 1.PriorityOrdered 2 Ordered 3 rest 4 internalPostProcessors
    其中internalPostProcessors 屬于PriorityOrdered 和Ordered 同時(shí)是MergedBeanDefinitionPostProcessor 主要是修改RootBeanDefinition
  • RootBeanDefinition 它可能來源于多個(gè)原始Bean定義(繼承自其他的bean定義,通常被注冊(cè)為GenericBeanDefinitions)。RootBeanDefinition從本質(zhì)上將是運(yùn)行時(shí)統(tǒng)一的Bean定義視圖。
    在配置階段,RootBeanDefinition也可能用于注冊(cè)獨(dú)立的bean定義。然而,自從Spring2.5依賴,編程地注冊(cè)bean定義建議使用 GenericBeanDefinition類。GenericBeanDefinition在允許動(dòng)態(tài)定義父依賴而不是硬編碼作為RootBeanDefinition方面有優(yōu)勢(shì)。
  • 然后依次注冊(cè) PriorityOrdered Ordered 注冊(cè)其他的
  • 最終在添加一個(gè)ApplicationListenerDetector,其主要是檢測(cè)哪些bean是ApplicationListener

initMessageSource

這個(gè)是處理國(guó)際化的,具體代碼如下:

protected void initMessageSource() {
        ConfigurableListableBeanFactory beanFactory = getBeanFactory();
        if (beanFactory.containsLocalBean(MESSAGE_SOURCE_BEAN_NAME)) {
            this.messageSource = beanFactory.getBean(MESSAGE_SOURCE_BEAN_NAME, MessageSource.class);
            // Make MessageSource aware of parent MessageSource.
            if (this.parent != null && this.messageSource instanceof HierarchicalMessageSource) {
                HierarchicalMessageSource hms = (HierarchicalMessageSource) this.messageSource;
                if (hms.getParentMessageSource() == null) {
                    // Only set parent context as parent MessageSource if no parent MessageSource
                    // registered already.
                    hms.setParentMessageSource(getInternalParentMessageSource());
                }
            }
            if (logger.isDebugEnabled()) {
                logger.debug("Using MessageSource [" + this.messageSource + "]");
            }
        }
        else {
            // Use empty MessageSource to be able to accept getMessage calls.
            DelegatingMessageSource dms = new DelegatingMessageSource();
            dms.setParentMessageSource(getInternalParentMessageSource());
            this.messageSource = dms;
            beanFactory.registerSingleton(MESSAGE_SOURCE_BEAN_NAME, this.messageSource);
            if (logger.isDebugEnabled()) {
                logger.debug("Unable to locate MessageSource with name '" + MESSAGE_SOURCE_BEAN_NAME +
                        "': using default [" + this.messageSource + "]");
            }
        }
    }
  • 首先檢測(cè)是否存在messageSource的bean,若是存在獲取這個(gè)bean 然后 若是存在父容器,就設(shè)置該父容器的messageSource為當(dāng)前容器的父messageSource,如果父容器不存在messageSource,就設(shè)置父容器本身。設(shè)置父messageSource的意義是當(dāng)messageSource無法解析就交給父messageSource
  • 若是不存在 設(shè)一個(gè)emtpymessageSource(DelegatingMessageSource ),繼續(xù)按照上述邏輯設(shè)置父MessageSource ,然后注冊(cè)該bean

initApplicationEventMulticaster 初始化容器的組播組件

  • beanFactory.containsLocalBean(beanName) 只會(huì)在當(dāng)前容器中查找對(duì)應(yīng)的beanName是否存在
protected void initApplicationEventMulticaster() {
        ConfigurableListableBeanFactory beanFactory = getBeanFactory();
        if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {
            this.applicationEventMulticaster =
                    beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);
            if (logger.isDebugEnabled()) {
                logger.debug("Using ApplicationEventMulticaster [" + this.applicationEventMulticaster + "]");
            }
        }
        else {
            this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
            beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);
            if (logger.isDebugEnabled()) {
                logger.debug("Unable to locate ApplicationEventMulticaster with name '" +
                        APPLICATION_EVENT_MULTICASTER_BEAN_NAME +
                        "': using default [" + this.applicationEventMulticaster + "]");
            }
        }
    }
  • 上述方法主要是查看當(dāng)前beanName是否存在對(duì)應(yīng)的ApplicationEventMulticaster ,存在就注冊(cè)該bean 不存在就設(shè)置SimpleApplicationEventMulticaster為組播組件

onRefresh的代碼如下:

    protected void onRefresh() {
        super.onRefresh();
        try {
            createWebServer();
        }
        catch (Throwable ex) {
            throw new ApplicationContextException("Unable to start web server", ex);
        }
    }

public static ThemeSource initThemeSource(ApplicationContext context) {
        if (context.containsLocalBean(THEME_SOURCE_BEAN_NAME)) {
            ThemeSource themeSource = context.getBean(THEME_SOURCE_BEAN_NAME, ThemeSource.class);
            // Make ThemeSource aware of parent ThemeSource.
            if (context.getParent() instanceof ThemeSource && themeSource instanceof HierarchicalThemeSource) {
                HierarchicalThemeSource hts = (HierarchicalThemeSource) themeSource;
                if (hts.getParentThemeSource() == null) {
                    // Only set parent context as parent ThemeSource if no parent ThemeSource
                    // registered already.
                    hts.setParentThemeSource((ThemeSource) context.getParent());
                }
            }
            if (logger.isDebugEnabled()) {
                logger.debug("Using ThemeSource [" + themeSource + "]");
            }
            return themeSource;
        }
        else {
            // Use default ThemeSource to be able to accept getTheme calls, either
            // delegating to parent context's default or to local ResourceBundleThemeSource.
            HierarchicalThemeSource themeSource = null;
            if (context.getParent() instanceof ThemeSource) {
                themeSource = new DelegatingThemeSource();
                themeSource.setParentThemeSource((ThemeSource) context.getParent());
            }
            else {
                themeSource = new ResourceBundleThemeSource();
            }
            if (logger.isDebugEnabled()) {
                logger.debug("Unable to locate ThemeSource with name '" + THEME_SOURCE_BEAN_NAME +
                        "': using default [" + themeSource + "]");
            }
            return themeSource;
        }
    }
    private void createWebServer() {
        WebServer webServer = this.webServer;
        ServletContext servletContext = getServletContext();
        if (webServer == null && servletContext == null) {
            ServletWebServerFactory factory = getWebServerFactory();
            this.webServer = factory.getWebServer(getSelfInitializer());
        }
        else if (servletContext != null) {
            try {
                getSelfInitializer().onStartup(servletContext);
            }
            catch (ServletException ex) {
                throw new ApplicationContextException("Cannot initialize servlet context",
                        ex);
            }
        }
        initPropertySources();
    }


    protected void initPropertySources() {
        ConfigurableEnvironment env = getEnvironment();
        if (env instanceof ConfigurableWebEnvironment) {
            ((ConfigurableWebEnvironment) env).initPropertySources(this.servletContext, null);
        }
    }

    protected ServletWebServerFactory getWebServerFactory() {
        // Use bean names so that we don't consider the hierarchy
        String[] beanNames = getBeanFactory()
                .getBeanNamesForType(ServletWebServerFactory.class);
        if (beanNames.length == 0) {
            throw new ApplicationContextException(
                    "Unable to start ServletWebServerApplicationContext due to missing "
                            + "ServletWebServerFactory bean.");
        }
        if (beanNames.length > 1) {
            throw new ApplicationContextException(
                    "Unable to start ServletWebServerApplicationContext due to multiple "
                            + "ServletWebServerFactory beans : "
                            + StringUtils.arrayToCommaDelimitedString(beanNames));
        }
        return getBeanFactory().getBean(beanNames[0], ServletWebServerFactory.class);
    }
    public WebServer getWebServer(ServletContextInitializer... initializers) {
        Tomcat tomcat = new Tomcat();
        File baseDir = (this.baseDirectory != null ? this.baseDirectory
                : createTempDir("tomcat"));
        tomcat.setBaseDir(baseDir.getAbsolutePath());
        Connector connector = new Connector(this.protocol);
        tomcat.getService().addConnector(connector);
        customizeConnector(connector);
        tomcat.setConnector(connector);
        tomcat.getHost().setAutoDeploy(false);
        configureEngine(tomcat.getEngine());
        for (Connector additionalConnector : this.additionalTomcatConnectors) {
            tomcat.getService().addConnector(additionalConnector);
        }
        prepareContext(tomcat.getHost(), initializers);
        return getTomcatWebServer(tomcat);
    }


    protected void prepareContext(Host host, ServletContextInitializer[] initializers) {
        File documentRoot = getValidDocumentRoot();
        TomcatEmbeddedContext context = new TomcatEmbeddedContext();
        if (documentRoot != null) {
            context.setResources(new LoaderHidingResourceRoot(context));
        }
        context.setName(getContextPath());
        context.setDisplayName(getDisplayName());
        context.setPath(getContextPath());
        File docBase = (documentRoot != null ? documentRoot
                : createTempDir("tomcat-docbase"));
        context.setDocBase(docBase.getAbsolutePath());
        context.addLifecycleListener(new FixContextListener());
        context.setParentClassLoader(
                this.resourceLoader != null ? this.resourceLoader.getClassLoader()
                        : ClassUtils.getDefaultClassLoader());
        resetDefaultLocaleMapping(context);
        addLocaleMappings(context);
        context.setUseRelativeRedirects(false);
        configureTldSkipPatterns(context);
        WebappLoader loader = new WebappLoader(context.getParentClassLoader());
        loader.setLoaderClass(TomcatEmbeddedWebappClassLoader.class.getName());
        loader.setDelegate(true);
        context.setLoader(loader);
        if (isRegisterDefaultServlet()) {
            addDefaultServlet(context);
        }
        if (shouldRegisterJspServlet()) {
            addJspServlet(context);
            addJasperInitializer(context);
        }
        context.addLifecycleListener(new StaticResourceConfigurer(context));
        ServletContextInitializer[] initializersToUse = mergeInitializers(initializers);
        host.addChild(context);
        configureContext(context, initializersToUse);
        postProcessContext(context);
    }

public TomcatWebServer(Tomcat tomcat, boolean autoStart) {
        Assert.notNull(tomcat, "Tomcat Server must not be null");
        this.tomcat = tomcat;
        this.autoStart = autoStart;
        initialize();
    }

    private void initialize() throws WebServerException {
        TomcatWebServer.logger
                .info("Tomcat initialized with port(s): " + getPortsDescription(false));
        synchronized (this.monitor) {
            try {
                addInstanceIdToEngineName();

                Context context = findContext();
                context.addLifecycleListener((event) -> {
                    if (context.equals(event.getSource())
                            && Lifecycle.START_EVENT.equals(event.getType())) {
                        // Remove service connectors so that protocol binding doesn't
                        // happen when the service is started.
                        removeServiceConnectors();
                    }
                });

                // Start the server to trigger initialization listeners
                this.tomcat.start();

                // We can re-throw failure exception directly in the main thread
                rethrowDeferredStartupExceptions();

                try {
                    ContextBindings.bindClassLoader(context, context.getNamingToken(),
                            getClass().getClassLoader());
                }
                catch (NamingException ex) {
                    // Naming is not enabled. Continue
                }

                // Unlike Jetty, all Tomcat threads are daemon threads. We create a
                // blocking non-daemon to stop immediate shutdown
                startDaemonAwaitThread();
            }
            catch (Exception ex) {
                stopSilently();
                throw new WebServerException("Unable to start embedded Tomcat", ex);
            }
        }
    }
  • 上述代碼主要是初始化ThemeSource,如果沒有就設(shè)置ResourceBundleThemeSource,整個(gè)邏輯類似于messageSource
  • 創(chuàng)建WebServer
  • 如果webServer和servletcontext都為null 則去獲取ServletWebServerFactory的bean
  • ServletContextInitializer 存在的作用主要是讓ServletContextInitializer 可以被spring容器管理 而不被servlet容器管理,且與WebApplicationInitializer不同的是 實(shí)現(xiàn)ServletContextInitializer 的實(shí)現(xiàn)類且未實(shí)現(xiàn)WebApplicationInitializer 不會(huì)被SpringServletContainerInitializer檢測(cè)到,因此不會(huì)有servlet容器自動(dòng)引導(dǎo)。其onStartup方法 主要是配置ServletContext,比如any servlets, filters, listeners context-params and attributes
  • WebApplicationInitializer 可以看做是Web.xml的替代,它是一個(gè)接口。通過實(shí)現(xiàn)WebApplicationInitializer,在其中可以添加servlet,listener等,在加載Web項(xiàng)目的時(shí)候會(huì)加載這個(gè)接口實(shí)現(xiàn)類,從而起到web.xml相同的作用

SpringServletContainerInitializer作為ServletContainerInitializer的實(shí)現(xiàn)類,通過SPI機(jī)制,在web容器加載的時(shí)候會(huì)自動(dòng)的被調(diào)用。(這個(gè)類上還有一個(gè)注解@HandlesTypes,它的作用是將感興趣的一些類注入到ServletContainerInitializerde), 而這個(gè)類的方法又會(huì)掃描找到WebApplicationInitializer的實(shí)現(xiàn)類,調(diào)用它的onStartup方法,從而起到啟動(dòng)web.xml相同的作用。

  • getWebServer 主要是設(shè)置設(shè)置和啟動(dòng)內(nèi)置tomcat 設(shè)置Connector (默認(rèn)Nio協(xié)議)customizeConnector調(diào)整Connector
  • prepareContext 就是設(shè)置host host內(nèi)部持有的是spring的TomcatEmbeddedContext
  • 最后獲取TomcatWebServer并初始化,即設(shè)置LifecycleListener并且啟動(dòng)tomcat

registerListeners

  • 主要是注冊(cè)ApplicationListener-當(dāng)容器初始化完成之后,需要處理一些操作,比如一些數(shù)據(jù)的加載、初始化緩存、特定任務(wù)的注冊(cè)等等。這個(gè)時(shí)候我們就可以使用Spring提供的ApplicationListener來進(jìn)行操作。
  • 然后發(fā)布earlyApplicationEvents

finishBeanFactoryInitialization

  • 設(shè)置beanFactory 的conversion service(其實(shí)作為JavaBeans PropertyEditors.的替代者 用來轉(zhuǎn)換屬性值)
  • 為嵌入值(例如注釋屬性)添加String解析器。
  • 盡早初始化LoadTimeWeaverAware bean以允許盡早注冊(cè)其變換器。
  • 將temporary ClassLoader設(shè)置為null
  • 凍結(jié)所有的beanDefinition,不允許更改
  • 實(shí)例所有非懶加載的bean對(duì)象

finishRefresh

  • 清除上下文級(jí)資源緩存(例如來自掃描的ASM元數(shù)據(jù))。
  • 初始化容器的lifecycle processor 比如smartLifeCycle
  • 按照phase的大小依次啟動(dòng)lifecycle processor
  • 發(fā)送ContextRefreshedEvent時(shí)間
  • 如果LiveBeansView MBean 激活了,則參與LiveBeansView MBean。

destroyBeans 摧毀所有的單例

cancelRefresh 設(shè)active標(biāo)識(shí)為false

resetCommonCaches

  • 清除反射的緩存
  • 清除注解的相關(guān)緩存
  • Clear the internal {@code ResolvableType}/{@code SerializableTypeWrapper} cache.
  • 清除classloader緩存

內(nèi)置tomcat的說明

內(nèi)置tomcat的懸疑
首先創(chuàng)建ServletWebServerFactory的bean
然后調(diào)用其getWebServer生成WebServer
然后在創(chuàng)建baseDir,根據(jù)協(xié)議創(chuàng)建Connector和ProtocolHandler(協(xié)議處理器)
這個(gè)ProtocolHandler主要是設(shè)置adapter和Endpoint,而 adapter可以調(diào)用connector
adapter提供了service,prepare,asyncDispatch,log,checkRecycled,getDomain
其中domain是用來注冊(cè)跟這個(gè)connector關(guān)聯(lián)的Mbeans
然后創(chuàng)建service,connector,container(enigne),添加valve
下面關(guān)鍵的就來了 我們知道container的順序是engine,host,context,wrapper
我們這邊創(chuàng)建了一個(gè)TomcatEmbeddedContext,將spring容器塞入TomcatEmbeddedContext
同時(shí)創(chuàng)建一個(gè)WebappLoader給當(dāng)前的TomcatEmbeddedContext
創(chuàng)建一個(gè)Wrapper塞入TomcatEmbeddedContext
通過把我們spring容器包裝成ServletContextInitializer
然后配置我們的context 包括設(shè)置starter(其就是我們ServletContextInitializer的集合類)
設(shè)置Valve,ErrorPage,MimeMappings
然后我們啟動(dòng)tomcat(啟動(dòng)server)
最終我們調(diào)用ServletWebServerApplicationContext的selfInitialize,其主要是把spring容器
和servletContext 互相綁定,當(dāng)我們請(qǐng)求時(shí)候tomcat最終會(huì)調(diào)用dispatchServlet,然后把spring容器設(shè)置
為該servlet的屬性,這樣就可以在該servlet使用spring提供的功能

ProtocolHandler 內(nèi)部包含一個(gè)endpoint 也就是說該協(xié)議采用
endpoint 進(jìn)行底層的socket的通信
可以把Endpoint理解 為netty的serverbootStrap

當(dāng)endpoint發(fā)現(xiàn)需要處理的socket,會(huì)創(chuàng)建一個(gè)SocketProcessor
最終會(huì)調(diào)用ProtocolHandler的process方法,該方法會(huì)創(chuàng)建一個(gè)Processor
該P(yáng)rocessor會(huì)包含adapter,其他的請(qǐng)求信息等
最終adapter會(huì)交給對(duì)應(yīng)的container

--
Valve和ContainerBackgroundProcessor
一般只會(huì)給engine啟動(dòng)一個(gè)線程去執(zhí)行ContainerBackgroundProcessor
而該任務(wù)會(huì)執(zhí)行當(dāng)前container和其子類容器的 backgroundProcess();
而 一般container的backgroundProcess不僅僅包含container本身還包含該
container的pipeline的valve的backgroundProcess

一般接受一個(gè)請(qǐng)求的流程是
Endpoint.Acceptor的acceptor線程接受到請(qǐng)求
一層層處理交給Adapter
而Adapter主要就是調(diào)用其service方法把
org.apache.coyote.Request req, org.apache.coyote.Response res
轉(zhuǎn)換為HttpServletRequest和HttpServletResponse
然后交給engine的第一個(gè)valve處理

每個(gè)容器都有一個(gè)pipeline 里面存儲(chǔ)鏈表valve
其最后一個(gè)valve都是負(fù)責(zé)連接下一個(gè)container

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 1.1 Spring IoC容器和bean簡(jiǎn)介 本章介紹了Spring Framework實(shí)現(xiàn)的控制反轉(zhuǎn)(IoC)...
    起名真是難閱讀 2,681評(píng)論 0 8
  • 1.1 spring IoC容器和beans的簡(jiǎn)介 Spring 框架的最核心基礎(chǔ)的功能是IoC(控制反轉(zhuǎn))容器,...
    simoscode閱讀 6,856評(píng)論 2 22
  • Spring容器高層視圖 Spring 啟動(dòng)時(shí)讀取應(yīng)用程序提供的Bean配置信息,并在Spring容器中生成一份相...
    Theriseof閱讀 2,920評(píng)論 1 24
  • 本來是準(zhǔn)備看一看Spring源碼的。然后在知乎上看到來一個(gè)帖子,說有一群**自己連Spring官方文檔都沒有完全讀...
    此魚不得水閱讀 7,049評(píng)論 4 21
  • 最近這幾天,都在練邏輯思維……不要太浮躁……不要太浮躁……不要太浮躁…… 看看余姚的變化,同一個(gè)老師,為什么差別那...
    小小小grow閱讀 185評(píng)論 0 0

友情鏈接更多精彩內(nèi)容