DispatcherServlet与IOC容器有何区别?Web应用启动时二者如何工作?
一、二者各自的作用
1. IOC容器的作用
- 是Spring框架的核心底座,负责全应用Bean的生命周期管理、依赖注入装配。启动时会扫描配置路径下的
@Component、@Service、@Repository、@Controller等注解,自动实例化对象、完成依赖绑定,完全避免硬编码的对象创建逻辑。 - 常规Spring MVC架构下会分为两层:根IOC容器管理业务层、持久层的通用Bean,全局共享;DispatcherServlet持有的子IOC容器,只管理Controller、视图解析器、处理器映射器这类Web层专属Bean,子容器可以访问根容器的Bean,反过来根容器不能访问子容器的Bean。
2. DispatcherServlet的作用
- 是Spring MVC的核心前端控制器,所有客户端发起的HTTP请求都会先经过它,是请求分发的总入口。
- 启动阶段会初始化自己持有的子IOC容器,加载Web层相关的组件配置,绑定到Servlet上下文。
- 运行阶段会根据请求路径匹配对应的Controller方法,自动完成参数绑定、返回值解析、全局异常处理等逻辑,最终把处理结果返回给客户端。
二、二者的调用时机
Web应用启动时二者的执行顺序是固定的:
- 首先Servlet容器(比如Tomcat、Jetty)启动,读取web.xml或者Spring Boot的自动配置类,触发ServletContext的初始化回调。
- 优先初始化根IOC容器:加载全局配置,扫描业务层、持久层的Bean完成实例化,初始化完成后会把容器实例存入ServletContext的公共属性中,供整个应用访问。
- 根IOC容器初始化完成后,才会触发DispatcherServlet的初始化:Servlet容器调用DispatcherServlet的
init()方法,此时它会创建自己的子IOC容器,把根容器设为父容器,然后扫描Web层的Bean完成装配,同时初始化处理器映射、参数解析器等Web核心组件。 - 所有组件初始化完成后,应用正式启动可以接收客户端请求。
小提示:Spring Boot默认会把根容器和Servlet子容器合并为一个简化配置,但逻辑上的分层规则仍然生效。
三、实际场景示例
我们用一个简单的用户查询接口来演示完整流程,代码结构如下:
// 业务层Bean,归根IOC容器管理 @Service public class UserService { public User getById(Long id) { // 模拟数据库查询逻辑 return new User(id, "张三", 25); } } // Web层Bean,归DispatcherServlet的子容器管理 @RestController @RequestMapping("/user") public class UserController { // 子容器可以直接注入根容器托管的UserService @Autowired private UserService userService; @GetMapping("/{id}") public User getById(@PathVariable Long id) { return userService.getById(id); } }
启动和运行的完整流程:
- Tomcat启动后先初始化根IOC容器,扫描到带
@Service注解的UserService,实例化后存入根容器。 - 接下来初始化DispatcherServlet,创建子容器扫描到带
@RestController注解的UserController,实例化时从根容器找到已经初始化好的UserService注入到Controller中。 - DispatcherServlet同步初始化处理器映射器,把
GET /user/{id}路径和UserController的getById方法做绑定。 - 客户端发起
GET /user/1请求时,请求首先到达DispatcherServlet,它根据路径匹配到对应的方法执行,最后把返回结果序列化为JSON返回给客户端。
我们可以做个反向验证:如果把UserService的@Service注解删掉,启动时根容器就不会实例化UserService,DispatcherServlet初始化UserController时就会直接抛出找不到对应Bean的异常,也能印证二者的依赖关系。
内容的提问来源于stack exchange,提问作者Soham Narang
相关产品推荐
相关产品推荐

