SpringBoot本身并没有直接利用SpringFramework现有的IOC容器,而是针对嵌入式Web容器的这一核心特性扩展了更强大的IOC容器。SpringBoot针对WebMvc与WebFlux(用于构建异步非阻塞式Web应用)这两种Web应用的搭建基础分别扩展了不同的IOC容器。
Interface to be implemented by
ApplicationContext
that create and manage the lifecycle of an embeddedWebServer
.
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容器实例。
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() {
// ...
}
}
SpringBoot 2.x基于SpringFramework 5.x,而5.x版本引入了新的WebFlux模块,因此IOC容器就不只有基于Servlet环境的最终实现,还有基于ReactiveWeb环境的实现。
基于ReactiveWeb环境的实现也有一套“接口-实现类”的体系,与基于Servlet环境的命名方式如出一辙:
SpringBoot为什么选择注解驱动的IOC容器,而放弃曾经主推的XML配置?
SpringFramework刚出现的时候,只能使用XML配置文件的方式驱动IOC容器,直到SpringFramework 3.x后才支持注解驱动配置。
因此,XML配置文件是早期采用的配置方式,注解配置类则相对晚一些。、
XML配置文件修改灵活,无须重新编译,并且IOC容器可以反复刷新加载配置文件;
注解配置类修改不那么灵活,每次修改后需要重新编译、打包,并且IOC容器只能加载一次,无法反复刷新。
因此,在修改灵活性上,XML配置文件更有优势。
XML配置文件的内容编写需要符合相关的规范,规范以外的内容SpringFramework不会认可;
注解配置类的内容编写相对灵活,SpringFramework 3.1提供的模块装配,4.0提供的条件装配可以使配置的编写非常灵活,且可以根据不同场景的要求注入不同类型的组件。
因此,在内容编写上,注解配置类更有优势。
SpringBoot的核心设计之一是:约定大于配置,这种设计更加强调项目环境与自定义配置间的配合协作(已经配置的不重复注册,没有配置的自动补充)。
XML配置文件方式对于配置的编写更灵活、易修改,但在整合具体场景时这种优势荡然无存。因为在实际的项目开发中,我们不会轻易改动现有jar包中的文件,更何况还是配置文件。同时,XML文件中定义了组件,会实实在在注册到IOC容器中,运行时的灵活性较差;
基于注解配置类的方式支持模块装配、条件装配、SPI机制等高级特性,在整合具体场景时,完全可以实现与项目中自定义配置的相互配合,即实现了约定大于配置。
综上所述,SpringBoot推荐使用注解驱动的配置方式。