Spring MVC中的Controller加载控制与Bean加载控制详解

server/2025/3/15 1:11:29/

    Spring MVC默认通过父子容器实现Web层与非Web组件的隔离。但在实际项目中,若未明确控制组件的扫描路径与加载规则,表现层的Controller、业务层的Service与数据层的Repository往往会被“一刀切”地扫描到同一上下文中。例如,业务层的Service被意外注册到Spring MVC的Web上下文中,或数据源DataSource等基础设施Bean被表现层的组件直接依赖。这种混乱的加载方式不仅可能破坏分层架构的纯净性,还会导致事务管理失效、依赖注入冲突,甚至引发性能隐患。

加载控制

关键点:

在标准的 Spring MVC 应用中,存在 两个独立的上下文

上下文类型加载方式典型组件Bean 可见性
根上下文 (Root)ContextLoaderListenerService、Repository、DataSource对 Web 上下文可见
Web 上下文 (Servlet)DispatcherServletController、Interceptor、ViewResolver仅 Web 上下文内部可见
  • 父子关系:Web 上下文是根上下文的子上下文,因此 Web 上下文可以访问根上下文的 Bean,但根上下文无法访问 Web 上下文的 Bean。

  • 隔离性:若未正确分层,Web 上下文将无法获取业务层组件。

方案一:精确扫描

@Configuration
@ComponentScan("com.cc.controller")
public class SpringMvcConfig {
}

 方案二:过滤

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.FilterType;
import org.springframework.stereotype.Controller;
import org.springframework.stereotype.Repository;
import org.springframework.stereotype.Service;@Configuration
@ComponentScan(value = "com.cc" ,     //明确扫描哪个包 value同等于basePackageexcludeFilters = @ComponentScan.Filter(    //表示排除哪些包type = FilterType.ANNOTATION,classes = Controller.class),includeFilters = @ComponentScan.Filter(    //表示精确扫描哪些包type = FilterType.ANNOTATION,classes = {Service.class, Repository.class})
)
public class SpringConfig {
}

测试:首先将spriongMvcConfig中的注解注释,仅让SpringConfig生效。写一个测试类看是否能获取UserController(在扫描SpringConfig时排除了Controller注解(见上面的代码),所以不能获取到):

import com.cc.config.SpringConfig;
import com.cc.controller.UserController;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;public class App {public static void main(String[] args) {AnnotationConfigApplicationContext a = new AnnotationConfigApplicationContext(SpringConfig.class);System.out.println(a.getBean(UserController.class));}
}

    接着回到SpringConfig,将排除的部分注释,如果能获取到则说明该方法可行:

简化开发 

    回到servlet容器,在springmvc环境和pring加载不同的配置:

public class ServletConfig extends AbstractDispatcherServletInitializer {//加载springmvc容器配置@Overrideprotected WebApplicationContext createServletApplicationContext() {AnnotationConfigWebApplicationContext app = new AnnotationConfigWebApplicationContext();app.register(SpringMvcConfig.class);return app;}//设置哪些请求归属springMVC处理@Overrideprotected String[] getServletMappings() {return new String[]{"/"};  //所有请求}//加载spring容器配置@Overrideprotected WebApplicationContext createRootApplicationContext() {AnnotationConfigWebApplicationContext app = new AnnotationConfigWebApplicationContext();app.register(SpringConfig.class);return app;}
}

    该方法可以从继承AbstractDispatcherServletInitializer换继承AbstractAnnotationConfigDispatcherServletInitializer:

public class ServletConfig extends AbstractAnnotationConfigDispatcherServletInitializer {@Overrideprotected Class<?>[] getRootConfigClasses() {return new Class[]{SpringConfig.class};}@Overrideprotected Class<?>[] getServletConfigClasses() {return new Class[]{SpringMvcConfig.class};}@Overrideprotected String[] getServletMappings() {return new String[]{"/"};}
}


http://www.ppmy.cn/server/175020.html

相关文章

RocketMQ开发实战篇

一、生产者开发指南 1. Java API使用详解 在使用RocketMQ进行消息生产时&#xff0c;首先需要引入相关的依赖。在Maven项目中&#xff0c;可以在pom.xml文件中添加以下依赖&#xff1a; <dependency><groupId>org.apache.rocketmq</groupId><artifactI…

PHP与数据库连接常见问题及解决办法

PHP与数据库连接常见问题及解决办法 在现代Web开发中&#xff0c;PHP与数据库的连接是不可或缺的一部分。无论是构建动态网站、内容管理系统&#xff08;CMS&#xff09;还是电子商务平台&#xff0c;PHP与数据库的交互都是核心功能之一。然而&#xff0c;在实际开发过程中&am…

Linux调度器 --- 负载均衡的存在的问题

文章目录 前言一、简介二、Linux 调度器2.1 在单核系统上&#xff0c;CFS 非常简单2.2 在多核系统上&#xff0c;CFS 变得非常复杂2.2.1 负载均衡算法2.2.2 优化措施 三、Linux调度器负载均衡的存在的问题3.1 组负载不均衡问题&#xff08;Group Imbalance Bug&#xff09;3.2 …

Spring Boot启动流程及源码实现深度解析

Spring Boot启动流程及源码实现深度解析 一、启动流程概述 Spring Boot的启动流程围绕SpringApplication类展开&#xff0c;核心流程可分为以下几个阶段&#xff1a; 初始化阶段&#xff1a;推断应用类型&#xff0c;加载ApplicationContextInitializer和ApplicationListene…

php将身份证号写入excel文件出现科学计数法问题解决

在 PHP 中生成 Excel 文件并处理身份证号时&#xff0c;通常使用 PHPExcel 或其继任者 PhpSpreadsheet 库。身份证号通常是以字符串形式存储的&#xff0c;但在某些情况下&#xff0c;如果身份证号很长&#xff08;例如&#xff0c;超过 15 位数字&#xff09;&#xff0c;在 E…

【每日学点HarmonyOS Next知识】自定义对话框关闭、WaterFlow嵌套、状态栏颜色、滚动吸附、滚动动效

1、HarmonyOS 自定义对话框自动关闭的问题&#xff1f; 启动页做了个隐私协议弹窗&#xff0c;autoCancel为false。UI中使用 Text() ContainerSpan() Span()组件&#xff0c;设置了点击事件&#xff0c;点击后使用router.pushUrl()的方法跳转到协议页面。点击时&#xff0c;对…

自动化测试 | Python+PyCharm+Google Chrome+Selenium 环境安装记录

目录 环境版本 浏览器与驱动 Python 安装 测试 PyCharm 安装 开启软件 开始破解 Selenium 安装 测试 自动化的其实就是模拟手工点击的方式 环境版本 Python&#xff1a;3.11.8 PyCharm&#xff1a;2021.1.3 Selenium&#xff1a;x.x 浏览器与驱动 114.0.5735.90 …

【面试题系列】 Redis 核心面试题(二)答案

本文主要介绍Redis 的面试题&#xff0c;涵盖持久化、集群、缓存策略、事务等方面 一、持久化机制 1. RDB 与 AOF 的核心区别及适用场景&#xff1f; 答案&#xff1a; 特性RDBAOF存储内容内存快照&#xff08;二进制文件&#xff09;写命令日志&#xff08;文本格式&#x…