SpringBoot源码解读与原理分析(二十七)嵌入式Tomcat

这篇具有很好参考价值的文章主要介绍了SpringBoot源码解读与原理分析(二十七)嵌入式Tomcat。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

前言

当Web应用需要部署运行时,传统的做法是将项目打包成war包,然后部署到外置的Web容器中(如最常用的Tomcat容器)。SpringBoot的一大重要特性是支持嵌入式Web容器,基于SpringBoot的Web应用仅凭一个单独的jar包即可独立运行。

8.1 嵌入式Tomcat简介

8.1.1 嵌入式Tomcat与普通Tomcat

嵌入式Tomcat是一种可以嵌入到Web应用中,无需单独部署的Tomcat容器。

普通的外置Tomcat与嵌入式Tomcat从核心、本质上看没有任何区别,都可以承载Web应用的运行。

但SpringBoot整合嵌入式Tomcat容器时在底层设定了一些额外的限制。

  • 部署应用的限制:由于嵌入式Tomcat不是独立的Web容器,而是嵌入到特定的Web应用中的,因此该嵌入式Tomcat容器只能部署这一个特定的Web应用。
  • web.xml的限制:SpringBoot整合嵌入式Tomcat后不再对web.xml文件予以支持。
  • Servlet原生三大组件的限制:原生的基于Servlet 3.0及以上规范的Web项目,其类路径下的Servlet、Filter、Listener可以被自动扫描并注册,而SpringBoot整合嵌入式Tomcat后该特性失效。如果需要开启该特性,需要配合@ServletConponentScan注解使用。
  • JSP的限制:SpringBoot整合嵌入式Tomcat后,如果以独立jar包的方式启动项目(java -jar),则JSP页面会失效;如果以war包的方式部署到外置的Tomcat容器,则JSP页面可以正常运行。

8.1.2 Tomcat整体架构

SpringBoot源码解读与原理分析(二十七)嵌入式Tomcat,SpringBoot源码解读与原理分析,spring boot,tomcat,后端,spring,java
图片来源于CSDN文章:Tomcat.02结构图&启动&server.xml&连接器

从架构图可以得出Tomcat的架构设计如下:

  • 一个Tomcat服务器是一个Server;
  • 一个Server包含多个服务Service,其中提供默认HTTP请求响应服务的是Catalina;
  • 一个Service包含多个Connector,用于与客户端交互,实现接收客户端请求并转发到Engine和接收Engine响应结果并响应给客户端;
  • 一个Service还包含一个Container Engine,用于真正处理客户端的请求,并响应结果;
  • 一个Container Engine包含多个Host,每个Host可以装在多个Web应用;
  • 一个Web应用对应一个Context,一个Context包含多个Servlet。

8.1.3 Tomcat的核心工作流程

Tomcat作为一个Web服务器,其核心工作是接收客户端发起的HTTP请求,转发给服务器端的Web应用处理,处理完成后将结果响应给客户端。

其工作流程大致如下:

1、请求进入Tomcat容器,Tomcat容器内部根据请求URL,判断该请求应该由哪个应用来处理,并将请求封装为ServletRequest对象,转发至对应的Web应用中的Context。
2、Context接收到ServletRequest对象后,根据请求URI定位可以接收当前请求的Servlet,并将请求转发给具体的Servlet进行处理。
3、在转发到Servlet之前,容器会检查对应的Servlet是否已加载,如果没有加载,则会利用反射机制创建Servlet对象,并调用其init方法完成初始化,之后再进行逻辑处理。
4、Servlet处理完成后,将响应结果以ServletResponse对应响应给Service中的Connector,由Connector响应给客户端,至此完成一次请求处理。

8.2 SpringBoot中嵌入式容器的模型

SpringBoot支持的嵌入式容器包括Tomcat、Jetty、Undertow、Netty等。

8.2.1 WebServer

代码清单1WebServer.java|TomcatWebServer.java

public interface WebServer {
    void start() throws WebServerException;
    void stop() throws WebServerException;
    // ...
}

public class TomcatWebServer implements WebServer {
    private final Tomcat tomcat;
    // ...
}

由 代码清单1 可知,WebServer是SpringBoot针对所有嵌入式Web容器制定的顶级接口,定义了嵌入式Web容器的启动和停止动作。

实现WebServer接口的实现类通常会在内部组合一个真正的嵌入式容器,如TomcatWebServer中包含一个Tomcat对象,并重写start方法实现嵌入式Web容器的启动逻辑,重写stop方法实现嵌入式Web容器的停止和销毁逻辑。

8.2.2 WebServerFactory

代码清单2WebServerFactory.java

public interface WebServerFactory {
}

由 代码清单2 可知,WebServerFactory接口没有定义任何方法,仅为标记性接口

WebServerFactory是所有具备创建WebServer能力的工厂对象的根接口。

代码清单3ConfigurableWebServerFactory.java

public interface ConfigurableWebServerFactory extends WebServerFactory, ErrorPageRegistry {
    void setPort(int port);
    void setSsl(Ssl ssl);
    // ...
    // 优雅停机
    default void setShutdown(Shutdown shutdown) {
	}
}

由 代码清单3 可知,ConfigurableWebServerFactory是WebServerFactory的扩展接口,具备对WebServerFactory的配置能力(包括配置端口、SSL等)。

值得注意的是,嵌入式Web容器具有优雅停机的特性,即容器在关闭时不直接终止进程,而是预留一些时间使容器内部的业务线程全部处理完毕后才关停容器服务。

8.2.3 ServletWebServerFactory和ReactiveWebServerFactory

代码清单4ServletWebServerFactory.java|ReactiveWebServerFactory.java

public interface ServletWebServerFactory {
    WebServer getWebServer(ServletContextInitializer... initializers);
}

public interface ReactiveWebServerFactory {
    WebServer getWebServer(HttpHandler httpHandler);
}

由 代码清单4 可知,这是两个平级接口,分别是Servlet和Reactive场景下的嵌入式容器创建工厂。getWebServer方法的定义仅是入参不同(不同类型的Web容器在创建时传入的初始化组件不同),但都返回WebServer对象。

8.2.4 ConfigurableServletWebServerFactory

代码清单5ConfigurableServletWebServerFactory.java

public interface ConfigurableServletWebServerFactory extends ConfigurableWebServerFactory, ServletWebServerFactory {
    void setContextPath(String contextPath);
    void setInitializers(List<? extends ServletContextInitializer> initializers);
    void addInitializers(ServletContextInitializer... initializers);
    void setInitParameters(Map<String, String> initParameters);
    // ...
}

由 代码清单5 可知,ConfigurableServletWebServerFactory是ConfigurableWebServerFactory和ServletWebServerFactory组合后产生的子接口,具备更多能力,如可以设置访问Web应用所需的context-path、设置ServletContextInitializer、设置初始化参数等。

8.3 嵌入式Tomcat的初始化

在 SpringBoot源码解读与原理分析(二十三)IOC容器的刷新(四) 中提到,IOC容器刷新的第9步的onRefresh方法是一个模板方法,需要子类实现。

ServletWebServerApplicationContext类就是其中一个子类,重写了onRefresh方法,用于嵌入式Web容器的初始化。

代码清单6ServletWebServerApplicationContext.java

@Override
protected void onRefresh() {
    super.onRefresh();
    try {
        createWebServer();
    } // catch ...
}

private void createWebServer() {
    WebServer webServer = this.webServer;
    ServletContext servletContext = getServletContext();
    // 如果WebServer和ServletContext均为null,则需要创建嵌入式Web容器
    if (webServer == null && servletContext == null) {
        // 获取WebServerFactory
        ServletWebServerFactory factory = getWebServerFactory();
        // 创建WebServer
        this.webServer = factory.getWebServer(getSelfInitializer());
        // 回调优雅停机的钩子
        getBeanFactory().registerSingleton("webServerGracefulShutdown",
                new WebServerGracefulShutdownLifecycle(this.webServer));
        // 回调容器启停的生命周期钩子
        getBeanFactory().registerSingleton("webServerStartStop",
                new WebServerStartStopLifecycle(this, this.webServer));
    } else if (servletContext != null) {
        try {
            getSelfInitializer().onStartup(servletContext);
        } catch (ServletException ex) {
            throw new ApplicationContextException("Cannot initialize servlet context", ex);
        }
    }
    initPropertySources();
}

protected ServletWebServerFactory getWebServerFactory() {
    String[] beanNames = getBeanFactory().getBeanNamesForType(ServletWebServerFactory.class);
    // ...
    return getBeanFactory().getBean(beanNames[0], ServletWebServerFactory.class);
}

由 代码清单6 可知,createWebServer方法中包含WebServer的创建,还有两个与生命周期回调相关的钩子。

8.3.1 创建TomcatWebServer

由 代码清单6 可知,创建嵌入式Web容器的入口是ServletWebServerFactory,其中嵌入式Tomcat容器的创建在其实现类TomcatServletWebServerFactory的getWebServer方法中实现。

代码清单7TomcatServletWebServerFactory.java

public static final String DEFAULT_PROTOCOL = "org.apache.coyote.http11.Http11NioProtocol";
private String protocol = DEFAULT_PROTOCOL;
@Override
public WebServer getWebServer(ServletContextInitializer... initializers) {
    // ...
    Tomcat tomcat = new Tomcat();
    // 给嵌入式Tomcat创建一个临时文件夹,用于存放Tomcat运行中需要的文件
    File baseDir = (this.baseDirectory != null) ? this.baseDirectory : createTempDir("tomcat");
    tomcat.setBaseDir(baseDir.getAbsolutePath());
    // Connector中默认放入的protocol为NIO模式
    Connector connector = new Connector(this.protocol);
    connector.setThrowOnFailure(true);
    // 向Service中添加Connector,并执行定制规则
    tomcat.getService().addConnector(connector);
    customizeConnector(connector);
    tomcat.setConnector(connector);
    // 关闭热部署(因为嵌入式Tomcat不存在修改web.xml、war包等情况)
    tomcat.getHost().setAutoDeploy(false);
    configureEngine(tomcat.getEngine());
    for (Connector additionalConnector : this.additionalTomcatConnectors) {
        tomcat.getService().addConnector(additionalConnector);
    }
    // 生成TomcatEmbeddedContext上下文
    prepareContext(tomcat.getHost(), initializers);
    // 创建TomcatWebServer
    return getTomcatWebServer(tomcat);
}

由 代码清单7 可知,获取到WebServerFactory后,下一步会执行getWebServer方法创建嵌入式Tomcat。

该方法核心步骤大致分为三步:创建Tomcat对象,并初始化基础的Connector和Engine;prepareContext方法初始化Context,构建应用上下文;getTomcatWebServer方法创建最终的TomcatWebServer对象。

8.3.1.1 prepareContext
代码清单8TomcatServletWebServerFactory.java

protected void prepareContext(Host host, ServletContextInitializer[] initializers) {
    File documentRoot = getValidDocumentRoot();
    // 创建Context
    TomcatEmbeddedContext context = new TomcatEmbeddedContext();
    // ...
    // 配置生命周期监听器等
    // ...
    // 应用ServletContextInitializer
    ServletContextInitializer[] initializersToUse = mergeInitializers(initializers);
    // Context添加到Host中
    host.addChild(context);
    configureContext(context, initializersToUse);
    postProcessContext(context);
}

由 代码清单8 可知,prepareContext方法的环节包括创建Tomcat内置上下文对象、配置生命周期监听器、应用ServletContextInitializer等。

  • ServletContextInitializer的设计

ServletContextInitializer本身并不是Servlet相关规范中定义的API,它是SpringBoot 1.4.0以后定义的API接口,这也说明ServletContextInitializer与某个具体的Web容器没有任何关系

借助IDEA,可以发现ServletContextInitializer的其中一个实现类RegistrationBean,而它又是Servlet三大核心组件的注册实现类ServletRegistrationBean、FilterRegistrationBean、ServletListenerRegistrationBean的父类。

如此来看,Servlet三大核心组件应会通过ServletContextInitializer与嵌入式Tomcat对接。

代码清单9TomcatServletWebServerFactory.java

protected void configureContext(Context context, ServletContextInitializer[] initializers) {
    TomcatStarter starter = new TomcatStarter(initializers);
    if (context instanceof TomcatEmbeddedContext) {
        TomcatEmbeddedContext embeddedContext = (TomcatEmbeddedContext) context;
        embeddedContext.setStarter(starter);
        embeddedContext.setFailCtxIfServletStartFails(true);
    }
    context.addServletContainerInitializer(starter, NO_CLASSES);
    // ...
}

由 代码清单8、9 可知,prepareContext方法倒数第2行有对ServletContextInitializer的配置应用,即调用configureContext方法,该方法会在内部实例化一个TomcatStarter对象,并加载到Servlet容器中。

代码清单10TomcatStarter.java

class TomcatStarter implements ServletContainerInitializer {
    private final ServletContextInitializer[] initializers;
    @Override
    public void onStartup(Set<Class<?>> classes, ServletContext servletContext) throws ServletException {
        try {
            for (ServletContextInitializer initializer : this.initializers) {
                initializer.onStartup(servletContext);
            }
        } // catch ...
    }
}

由 代码清单10 可知,TomcatStarter对象本身也是一个ServletContainerInitializer,被Servlet容器加载后,调用其onStartup方法。在该方法内部,会循环调用所有ServletContextInitializer的onStartup方法,由此完成Servlet原生三大核心组件的注册。

8.3.1.2 getTomcatWebServer

prepareContext方法执行完后,会执行getTomcatWebServer方法,以创建TomcatWebServer对象。

代码清单11TomcatServletWebServerFactory.java

protected TomcatWebServer getTomcatWebServer(Tomcat tomcat) {
    return new TomcatWebServer(tomcat, getPort() >= 0, getShutdown());
}
代码清单12TomcatWebServer.java

public TomcatWebServer(Tomcat tomcat, boolean autoStart, Shutdown shutdown) {
    Assert.notNull(tomcat, "Tomcat Server must not be null");
    this.tomcat = tomcat;
    this.autoStart = autoStart;
    this.gracefulShutdown = (shutdown == Shutdown.GRACEFUL) ? new GracefulShutdown(tomcat) : null;
    initialize();
}

由 代码清单11、12 可知,TomcatWebServer的初始化逻辑在其initialize方法中。

(1)获取Context
代码清单13TomcatWebServer.java

private void initialize() throws WebServerException {
    // ...
    //(1)获取第一个可用的Context
    Context context = findContext();
    //...
}

private Context findContext() {
    for (Container child : this.tomcat.getHost().findChildren()) {
        if (child instanceof Context) {
            return (Context) child;
        }
    }
    throw new IllegalStateException("The host does not contain a Context");
}

由 代码清单13 可知,initialize方法的第一个核心动作获取Tomcat中第一个可用的Context,即调用findContext方法。findContext方法会从Host中获取第一个类型为Context的子元素并返回。

实际上,这里获取到的就是在prepareContext方法中创建的TomcatEmbeddedContext。

(2)阻止Connector初始化
代码清单14TomcatWebServer.java

private void initialize() throws WebServerException {
    // ...
    //(2)添加LifecycleListener,移除Connector
    context.addLifecycleListener((event) -> {
        if (context.equals(event.getSource()) && Lifecycle.START_EVENT.equals(event.getType())) {
            // javadoc:移除Service中的Connector,那么当服务启动后协议绑定就不会发生。
            removeServiceConnectors();
        }
    });
    // ...
}

由 代码清单14 可知,initialize方法的第二个核心动作是添加一个LifecycleListener,该监听器的功能是移除Service中的Connector,即阻止Connector初始化。

在 代码清单7 中,getWebServer方法创建了Connector并放入了Service中,为什么这里要移除掉呢?

那是因为,创建嵌入式Web容器的时机是在IOC容器刷新的第9步,早于第11步的 初始化所有剩下的单实例finishBeanFactoryInitialization方法,此时IOC容器中绝大多数单实例bean对象尚未初始化,还不具备提供服务的能力。

Connector的功能是与客户端交互,一旦Connector初始化完成,意味着Tomcat可以对外提供服务,即客户端可以成功访问到Tomcat服务。

为了访问客户端成功访问到暂时无法提供服务的Tomcat服务,需要先将Connector移除。

(3)启动Tomcat
代码清单15TomcatWebServer.java

private void initialize() throws WebServerException {
    // ...
    //(3)启动Tomcat
    this.tomcat.start();
    // ...
}

由 代码清单15 可知,initialize方法的第三个核心动作是启动Tomcat。

代码清单16Tomcat.java

public void start() throws LifecycleException {
    getServer();
    server.start();
}

public Server getServer() {
    // ...
    server = new StandardServer();
    // ...
    // 端口设置为-1,代表这是嵌入式Tomcat
    server.setPort( -1 );
    Service service = new StandardService();
    service.setName("Tomcat");
    server.addService(service);
    return server;
}
代码清单17LifecycleBase.java

@Override
public final synchronized void start() throws LifecycleException {
    // 前置判断 ...
    
    // 初始化
    if (state.equals(LifecycleState.NEW)) {
        init();
    } // else if ...

    try {
        setStateInternal(LifecycleState.STARTING_PREP, null, false);
        // 启动自身
        startInternal();
        // ...
    } // catch ...
}

由 代码清单16、17 可知,Tomcat引导Server初始化和启动时,会在获取到Server后调用其start方法,而start方法定义在所有Tomcat核心组件的共同父类LifecycleBase上。

值得注意的是,获取Server时端口号被设置为-1,代表这是嵌入式Tomcat,方便后续使用。

代码清单18LifecycleBase.java

@Override
public final synchronized void init() throws LifecycleException {
    if (!state.equals(LifecycleState.NEW)) {
        invalidTransition(Lifecycle.BEFORE_INIT_EVENT);
    }

    try {
        setStateInternal(LifecycleState.INITIALIZING, null, false);
        initInternal();
        setStateInternal(LifecycleState.INITIALIZED, null, false);
    } // catch ...
}

protected abstract void initInternal() throws LifecycleException;

由 代码清单18 可知,init方法依然由父类LifecycleBase定义,其中间的initInternal方法是一个模板方法,由子类实现。

代码清单19StandardServer.java

@Override
protected void initInternal() throws LifecycleException {
    super.initInternal();
    // ...
    for (Service service : services) {
        service.init();
    }
}

由 代码清单19 可知,StandardServer类实现了initInternal方法,在该方法中会触发Service的初始化。

通过查阅源码发现,service.init()内部会触发Connector的初始化,以及后续所有核心组件的初始化逻辑都大致相同。完整的逻辑可以通过下面这张时序图体现出来:

SpringBoot源码解读与原理分析(二十七)嵌入式Tomcat,SpringBoot源码解读与原理分析,spring boot,tomcat,后端,spring,java

(4)阻止Tomcat结束
代码清单20TomcatWebServer.java

private void initialize() throws WebServerException {
    // ...
    //(4)阻止Tomcat结束
    startDaemonAwaitThread();
    // ...
}

private void startDaemonAwaitThread() {
    // 创建一个新线程
    Thread awaitThread = new Thread("container-" + (containerCounter.get())) {
        @Override
        public void run() {
            TomcatWebServer.this.tomcat.getServer().await();
        }
    };
    awaitThread.setContextClassLoader(getClass().getClassLoader());
    // 将该线程设置为非守护进程
    awaitThread.setDaemon(false);
    awaitThread.start();
}

由 代码清单20 可知,initialize方法的第四个核心动作是启动一个新的awaitThread线程,以阻止Tomcat进程结束,其内部实现的run方法是回调Server的await方法。

  • Daemon(守护)线程

在一个Java应用中,只要有一个非Daemon线程在运行,Daemon线程就不会停止,整个应用也不会终止。

如果Tomcat需要一直运行以接收客户端请求,就必须让Tomcat内部的Daemon进程都存活,至少需要一个能阻止Tomcat进程停止的非Daemon进程,而这里创建的awaitThread进程,将其Daemon设置为false,就是要负责阻止Tomcat进程停止。

  • await方法
代码清单21StandardServer.java

public void await() {
    // -2 时的处理 ...
    
    // 如果关闭Tomcat的端口是-1,代表是嵌入式Tomcat
    if (getPortWithOffset() == -1) {
        try {
            awaitThread = Thread.currentThread();
            while(!stopAwait) {
                try {
                    Thread.sleep( 10000 );
                } catch( InterruptedException ex ) {
                    // continue and check the flag
                }
            }
        } finally {
            awaitThread = null;
        }
        return;
    }
    
    // 退出端口的其他处理 ...
}

由 代码清单21 可知,如果关闭Tomcat的端口是-1,代表是嵌入式Tomcat(详见(3)启动Tomcat)。阻塞Tomcat进程结束的方式是每隔10s检查一次stopAwait的值,只要该值一直为false,Tomcat就不会退出。

······

经过上述一系列核心组件的初始化和启动,嵌入式Tomcat容器初始化完成。但此时Tomcat还不能提供服务,因为Connector在该阶段被移除,无法与客户端建立有效连接。

8.3.2 Web容器关闭相关的回调

由 代码清单6 可知,createWebServer方法中还有两个与生命周期回调相关的钩子。

8.3.2.1 WebServerGracefulShutdownLifecycle
代码清单22WebServerGracefulShutdownLifecycle.java

class WebServerGracefulShutdownLifecycle implements SmartLifecycle {
    private final WebServer webServer;
    WebServerGracefulShutdownLifecycle(WebServer webServer) {
        this.webServer = webServer;
	}
    @Override
    public void stop(Runnable callback) {
        this.running = false;
        this.webServer.shutDownGracefully((result) -> callback.run());
    }
}

由 代码清单22 可知,WebServerGracefulShutdownLifecycle用于触发嵌入式Web容器优雅停机的核心生命周期回调,它实现了SmartLifecycle接口,可以在IOC容器销毁阶段回调其stop方法以触发销毁逻辑。

stop方法会回调WebServer的shutDownGracefully方法实现优雅停机。

8.3.2.2 WebServerStartStopLifecycle
代码清单23WebServerStartStopLifecycle.java

class WebServerStartStopLifecycle implements SmartLifecycle {
    private final WebServer webServer;
    WebServerStartStopLifecycle(WebServer webServer) {
        this.webServer = webServer;
	}
    @Override
    public void start() {
        this.webServer.start();
        this.running = true;
        this.applicationContext
            .publishEvent(new ServletWebServerInitializedEvent(this.webServer, this.applicationContext));
    }
    
    @Override
    public void stop() {
        this.webServer.stop();
    }
}

由 代码清单23 可知,WebServerStartStopLifecycle的作用启动和关闭嵌入式Web容器,它会在IOC容器刷新即将完成/销毁时被回调,从而回调WebServer的start/stop方法,真正启动/关闭嵌入式Web容器。

8.4 嵌入式Tomcat的启动

onRefresh方法执行完毕,后续的finishBeanFactoryInitialization方法执行完毕,IOC容器中所有非延迟加载的单实例bean对象均初始化完毕,此时会执行IOC容器刷新的第12步finishRefresh方法,该方法中会回调所有的SmartLifeCycle,其中就包括 8.3.2.2 中的WebServerStartStopLifecycle,它会在该阶段回调嵌入式Web容器的start方法,从而真正启动Web容器。

代码清单24WebServerManager.java

void start() {
    this.handler.initializeHandler();
    this.webServer.start();
    this.applicationContext
        .publishEvent(new ReactiveWebServerInitializedEvent(this.webServer, this.applicationContext));
}
代码清单25TomcatWebServer.java

public void start() throws WebServerException {
    synchronized (this.monitor) {
        if (this.started) {
            return;
        }
        try {
            // 还原、启动Connector
            addPreviouslyRemovedConnectors();
            Connector connector = this.tomcat.getConnector();
            if (connector != null && this.autoStart) {
                performDeferredLoadOnStartup();
            }
            checkThatConnectorsHaveStarted();
            this.started = true;
            logger.info("Tomcat started on port(s): " + getPortsDescription(true) + " with context path '"
                    + getContextPath() + "'");
        } // catch ...
    }
}

private void addPreviouslyRemovedConnectors() {
    Service[] services = this.tomcat.getServer().findServices();
    for (Service service : services) {
        // 之前移除的Connector在serviceConnectors中
        Connector[] connectors = this.serviceConnectors.get(service);
        if (connectors != null) {
            for (Connector connector : connectors) {
                // 添加并启动Connector
                service.addConnector(connector);
                if (!this.autoStart) {
                    stopProtocolHandler(connector);
                }
            }
            this.serviceConnectors.remove(service);
        }
    }
}

由 代码清单24、25 可知,进入TomcatWebServer的start方法后,会调用addPreviouslyRemovedConnectors方法以还原并启动之前被移除掉的Connector(启动逻辑也在addConnector方法中)。

至此,嵌入式Tomcat完整启动。

8.5 小结

第8章到此就梳理完毕了,本章的主题是:嵌入式Web容器。回顾一下本章的梳理的内容:

(二十七)嵌入式Tomcat容器

更多内容请查阅分类专栏:SpringBoot源码解读与原理分析

第9章主要梳理:AOP模块的生命周期。主要内容包括:文章来源地址https://www.toymoban.com/news/detail-835221.html

  • AOP的核心后置处理器AnnotationAwareAspectJAutoProxyCreator;
  • AOP底层收集切面类的机制;
  • Bean被AOP代理的过程原理;
  • 代理对象执行的全流程分析。

到了这里,关于SpringBoot源码解读与原理分析(二十七)嵌入式Tomcat的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Spring Boot源码解读与原理分析

      最近机缘巧合之下,读到了 LinkedBear 编写的《Spring Boot源码解读与原理分析》这本书,本人花了一周的时间认真研读了一下这本书,真的是受益匪浅,特此推荐给大家,好书不容错过啊。 LinkedBear 是一名资深的Java开发工程师,常年致力于底层技术的研究,同时也通过技术

    2024年02月08日
    浏览(37)
  • 【框架源码】SpringBoot核心源码解读之启动类源码分析

    首先我们要先带着我们的疑问,spring boot是如何启动应用程序?去分析SpringBoot的启动源码。 我们在新建SpringBoot项目时,核心方法就是主类的run方法。 SpringApplication.run(ArchWebApplication.class, args) 我们点击run方法进入到源码中,这块传入的了一个我们当前程序主类的类对象以及主

    2024年02月06日
    浏览(28)
  • 《Spring Boot源码解读与原理分析》书籍推荐

    Spring Boot 1.0.0 早在2014年就已经发布,只不过到了提倡“降本增效”的今天,Spring Boot才引起了越来越多企业的关注。Spring Boot是目前Java EE开发中颇受欢迎的框架之一。依托于底层Spring Framework的基础支撑,以及完善强大的特性设计,Spring Boot已成为业界流行的应用和微服务开发

    2024年02月14日
    浏览(25)
  • SpringBoot学习之集成Swagger3(二十七)

    一、Maven配置 注意swagger的版本号是3.0.0版本以上才可以,这里我们就选择3.0.0版本  完整的Maven配置如下(仅供参考): project xmlns=\\\"http://maven.apache.org/POM/4.0.0\\\" xmlns:xsi=\\\"http://www.w3.org/2001/XMLSchema-instance\\\" xsi:schemaLocation=\\\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\\\"

    2024年02月05日
    浏览(47)
  • 【正点原子FPGA连载】 第二十七章OV5640摄像头LCD显示 摘自【正点原子】DFZU2EG_4EV MPSoC之嵌入式Vitis开发指南

    1)实验平台:正点原子MPSoC开发板 2)平台购买地址:https://detail.tmall.com/item.htm?id=692450874670 3)全套实验源码+手册+视频下载地址: http://www.openedv.com/thread-340252-1-1.html OV5640是OmniVision(豪威科技)公司生产的一颗CMOS图像传感器,该传感器功耗低、分辨率高以及采集速率快,主

    2024年02月16日
    浏览(45)
  • SpringBoot原理-自动配置-原理分析-源码跟踪

    SpringBootApplication 该注解标识在SpringBoot项目的启动类上,是SpringBoot中 最为重要 的注解,该注解由三个部分组成。 @SpringBootConfiguration:该注解与@Configuration注解作用一样,用来声明当前类为一个配置类 @ComponentScan:组件扫描,默认扫描当前启动类所在包及其子包 @EnableAutoConf

    2024年02月09日
    浏览(33)
  • SpringBoot:自动配置源码底层原理分析

    声明:原文作者:yuan_404 配置文件到底能写什么?怎么写? SpringBoot 官方文档中有大量的配置,我们无法全部记住 ,下面我们就梳理一下最核心的几个部分进行讲解。 以HttpEncodingAutoConfiguration(Http编码自动配置)为例解释自动配置原理; @Configuration(proxyBeanMethods = false) 表示

    2023年04月09日
    浏览(27)
  • Spark内容分享(二十七):阿里云基于 Spark 的云原生数据湖分析实践

    目录 Spark 与云原生的结合 1. 传统 Spark 集群的痛点 2. Spark 与云原生结合的优势 Spark on K8s 原理介绍 1. Spark 的集群部署模式 2. Spark on K8s 的部署架构 3. Spark on K8s 部署架构——对比 4. Spark on K8s 社区进展 5. Spark 3.3 新特性介绍 Spark on K8s 在阿里云 EMR 上的实践 1. EMR Spark on ACK 2. 充分

    2024年01月15日
    浏览(83)
  • SpringBoot源码分析(1)--@SpringBootApplication注解使用和原理/SpringBoot的自动配置原理详解

    springboot原理索引 SpringBoot源码分析(1)–@SpringBootApplication注解使用和原理/SpringBoot的自动配置原理详解 SpringBoot源码分析(2)–SpringBoot启动源码(万字图文源码debug讲解springboot启动原理) 本文主要讲解@SpringBootApplication注解使用和原理。 源码基于spring-boot-2.2.13.RELEASE进行讲解 主要是

    2024年02月13日
    浏览(30)
  • SpringBoot源码分析(4)--Environment(下)/配置文件加载原理

    SpringBoot源码分析 SpringBoot源码分析(1)–@SpringBootApplication注解使用和原理/SpringBoot的自动配置原理详解 SpringBoot源码分析(2)–SpringBoot启动源码(万字图文源码debug讲解springboot启动原理) SpringBoot源码分析(3)–Environment简介/prepareEnvironment准备环境(万字图文源码debug分析) 上一篇《

    2024年02月13日
    浏览(32)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包