SpringBoot源码解读与原理分析(九)SpringBoot对IOC容器的拓展

文章目录

    • 3.2 SpringBoot对IOC容器的拓展
      • 3.2.1 WebServerApplicationContext
      • 3.2.2 AnnotationConfigServletWebServerApplicationContext
      • 3.2.3 ReactiveWebApplicationContext
    • 3.3 SpringBoot选择注解驱动的原因
      • 3.3.1 配置方式的对比
        • 3.3.1.1 历史背景的比较
        • 3.3.1.2 修改灵活性的比较
        • 3.3.1.3 内容编写的比较
      • 3.3.2 约定大于配置的选择

了解了SpringFramework的IOC容器的两个核心接口BeanFactory和ApplicationContext之后,下面来看看SpringBoot对IOC容器的拓展,以及SpringBoot为什么选择注解配置类的IOC容器。

3.2 SpringBoot对IOC容器的拓展

SpringBoot本身并没有直接利用SpringFramework现有的IOC容器,而是针对嵌入式Web容器的这一核心特性扩展了更强大的IOC容器。SpringBoot针对WebMvc与WebFlux(用于构建异步非阻塞式Web应用)这两种Web应用的搭建基础分别扩展了不同的IOC容器。

3.2.1 WebServerApplicationContext

Interface to be implemented by ApplicationContextthat create and manage the lifecycle of an embedded WebServer.

WebServerApplicationContext是实现了ApplicationContext的接口,用于创建和管理嵌入式Web容器的生命周期。

注意:即使WebServer在类名上体现不出是嵌入式Web容器,但javadoc的描述告诉我们它就是指嵌入式Web容器。

public interface WebServerApplicationContext extends ApplicationContext {

    /**
     * Returns the ```WebServer```that was created by the context or ```null```if
     * the server has not yet been created.
     */
    WebServer getWebServer();
    
    // ...
}

WebServerApplicationContext接口中有一个重要方法:getWebServer。这个方法可以获取当前应用的嵌入式Web容器实例。换言之,ApplicationContext可以获取正在运行的Web容器实例。

3.2.2 AnnotationConfigServletWebServerApplicationContext

AnnotationConfigServletWebServerApplicationContext是SpringBoot整合WebMvc场景的IOC容器最终落地实现。根据类名,可以看出这个实现类的特性:注解驱动的(AnnotationConfig)、基于Servlet环境的(Servlet)、支持嵌入式Web容器(WebServer)的应用上下文。

SpringBoot默认使用注解驱动,所以落地实现都是用以AnnotationConfig为前缀的ApplicationContext类作为IOC容器支撑。

AnnotationConfigServletWebServerApplicationContext实现了AnnotationConfigRegistry接口,因此也具备该接口的特性:注解配置类的注册、模式注解的扫描。

AnnotationConfigServletWebServerApplicationContext还继承了ServletWebServerApplicationContext类,该类组合了嵌入式Web容器WebServer对象、ServletConfig配置对象,并且有创建嵌入式Web容器的逻辑。

public class ServletWebServerApplicationContext extends GenericWebApplicationContext
		implements ConfigurableWebServerApplicationContext {
    
    private volatile WebServer webServer;
    private ServletConfig servletConfig;
    // 创建嵌入式Web容器
    private void createWebServer() {
        // ...
    }
		    
}

3.2.3 ReactiveWebApplicationContext

SpringBoot 2.x基于SpringFramework 5.x,而5.x版本引入了新的WebFlux模块,因此IOC容器就不只有基于Servlet环境的最终实现,还有基于ReactiveWeb环境的实现。

基于ReactiveWeb环境的实现也有一套“接口-实现类”的体系,与基于Servlet环境的命名方式如出一辙:
SpringBoot源码解读与原理分析(九)SpringBoot对IOC容器的拓展_第1张图片

3.3 SpringBoot选择注解驱动的原因

SpringBoot为什么选择注解驱动的IOC容器,而放弃曾经主推的XML配置?

3.3.1 配置方式的对比

3.3.1.1 历史背景的比较

SpringFramework刚出现的时候,只能使用XML配置文件的方式驱动IOC容器,直到SpringFramework 3.x后才支持注解驱动配置。
因此,XML配置文件是早期采用的配置方式,注解配置类则相对晚一些。

3.3.1.2 修改灵活性的比较

XML配置文件修改灵活,无须重新编译,并且IOC容器可以反复刷新加载配置文件;
注解配置类修改不那么灵活,每次修改后需要重新编译、打包,并且IOC容器只能加载一次,无法反复刷新。
因此,在修改灵活性上,XML配置文件更有优势。

3.3.1.3 内容编写的比较

XML配置文件的内容编写需要符合相关的规范,规范以外的内容SpringFramework不会认可;
注解配置类的内容编写相对灵活,SpringFramework 3.1提供的模块装配,4.0提供的条件装配可以使配置的编写非常灵活,且可以根据不同场景的要求注入不同类型的组件。
因此,在内容编写上,注解配置类更有优势。

3.3.2 约定大于配置的选择

SpringBoot的核心设计之一是:约定大于配置,这种设计更加强调项目环境与自定义配置间的配合协作(已经配置的不重复注册,没有配置的自动补充)。

XML配置文件方式对于配置的编写更灵活、易修改,但在整合具体场景时这种优势荡然无存。因为在实际的项目开发中,我们不会轻易改动现有jar包中的文件,更何况还是配置文件。同时,XML文件中定义了组件,会实实在在注册到IOC容器中,运行时的灵活性较差;

基于注解配置类的方式支持模块装配、条件装配、SPI机制等高级特性,在整合具体场景时,完全可以实现与项目中自定义配置的相互配合,即实现了约定大于配置。

综上所述,SpringBoot推荐使用注解驱动的配置方式。

你可能感兴趣的:(spring,boot,java,后端,spring)