Spring和SpringMVC 父子容器的问题

简介: Spring与SpringMVC的容器属于父子容器关系,在配置使用SpringMVC时,若SpringMVC容器在Spring容器之前创建,可能会导致项目在编译运行时出现异常。

SpringMVC的父子容器问题

在使用SpringMVC 的时候,我们需要对前端控制器进行配置,前端控制器(DispatcherServlet)需要有一个 WebApplicationConetxt作为它的环境配置。


而 SpringMVC 作为 Spring 框架的一个子框架 ,自己拥有一个独立的子容器(Servlet WebApplicationContext),这个容器中应该包含 controller、view resolvers(视图适配器)、handlerMapping(处理器映射器)以及其他的一些和 web 相关的类;


但是如果在这个子容器中没有找到需要的组件(Component),那么SpringMVC 会到一个父容器的环境中(Root WebApplicationContext)去获取。而如果这个时候,父容器没有创建,那么就找不到对应的组件,编译器就会抛出异常,因此在配置前端控制器的时候,应该保证子容器当中可以获取到controller等的一些组件,并且父容器也要被创建。

image.pngimage.png

解决方法

在 springmvc.xml 中配置包扫描,扫描 controller 包

<?xmlversion="1.0" encoding="UTF-8"?><beansxmlns="http://www.springframework.org/schema/beans"xmlns:p="http://www.springframework.org/schema/p"xmlns:context="http://www.springframework.org/schema/context"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:mvc="http://www.alibaba.com/schema/stat"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsdhttp://www.alibaba.com/schema/stathttp://www.alibaba.com/schema/stat.xsd"><!--扫描controller--><context:component-scanbase-package="com.sxt.controller"/><!--配置spring注解的驱动(处理器映射器、处理器适配器)--><mvc:annotation-driven/><!--配置视图适配器--><beanclass="org.springframework.web.servlet.view.InternalResourceViewResolver"><propertyname="prefix"value="/view/"/><propertyname="suffix"value=".jsp"/></bean></beans>

情况一:在配置前端控制器的时候,使用通配符( * )来引入两个配置文件(springdao.xml [主容器配置文件]和 springmvc.xml [springMVC配置文件])

这种情况在理论上是可以满足需求的,但是由于使用的是通配符直接加载两个配置文件,不排除在创建的时候父容器之前就已经创建了子容器,这样也会出现错误

<!--配置前端控制器--><servlet><servlet-name>springmvc</servlet-name><servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class><init-param><param-name>contextConfigLocation</param-name><!--读取springmvc配置文件--><param-value>classpath:spring*.xml</param-value></init-param><load-on-startup>1</load-on-startup></servlet>

情况二:在 web.xml 中配置监听器(ContextLoaderListener),这个监听器在 web 启动的时候就会加载对应的 contextConfig 对应的配置文件,来创建父容器

<!--配置监听器--><!--该监听器可以使 web 在启动的时候加载contextConfig配置文件,创建application容器--><listener><listener-class>org.springframework.web.context.ContextLoaderListener</listener-class></listener><!--配置环境配置文件--><context-param><param-name>contextConfigLocation</param-name><param-value>classpath:springdao.xml</param-value></context-param>

情况三:前端控制器中配置 springdao.xml 作为它的环境配置(ContextConfiguration),并且在 springdao.xml 中通过 <import> 引入 springmvc.xml,这样来保证两个容器的创建顺序。

<!--配置前端控制器--><servlet><servlet-name>springmvc</servlet-name><servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class><init-param><param-name>contextConfigLocation</param-name><!--读取springmvc配置文件--><param-value>classpath:springdao.xml</param-value></init-param><load-on-startup>1</load-on-startup></servlet>

springdao.xml 文件配置:

<?xmlversion="1.0" encoding="UTF-8"?><beansxmlns="http://www.springframework.org/schema/beans"xmlns:p="http://www.springframework.org/schema/p"xmlns:context="http://www.springframework.org/schema/context"xmlns:tx="http://www.springframework.org/schema/tx"xmlns:aop="http://www.springframework.org/schema/aop"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsdhttp://www.springframework.org/schema/aophttps://www.springframework.org/schema/aop/spring-aop.xsdhttp://www.springframework.org/schema/txhttps://www.springframework.org/schema/tx/spring-tx.xsd"><!--设置注解配置包的扫描位置--><context:component-scanbase-package="com.sxt"/><!--配置读取db.properties数据库配置文件--><context:property-placeholderlocation="classpath:dbinfo.properties"/><!--配置数据库连接池--><beanid="dataSource"class="com.alibaba.druid.pool.DruidDataSource"><propertyname="driverClassName"value="${mysql.driver}"/><propertyname="url"value="${mysql.url}"/><propertyname="username"value="${mysql.username}"/><propertyname="password"value="${mysql.password}"/></bean><!--配置mybatis框架的 SqlSessionFactory 类,创建 SqlSessionFactory 工厂对象--><beanclass="com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean"id="sqlSessionFactory"><!--注入数据--><propertyname="dataSource"ref="dataSource"/><!--配置别名使用包扫描--><propertyname="typeAliasesPackage"value="com.sxt.bean"/><!--读取mybatis-config配置文件,实现其他个性配置--><propertyname="configLocation"value="classpath:mybatis-config.xml"/></bean><!--使用包扫描创建 Mapper 代理对象--><beanclass="org.mybatis.spring.mapper.MapperScannerConfigurer"><!--配置需要创建Mapper接口代理对象对应的包--><propertyname="basePackage"value="com.sxt.mapper"/><!--配置SqlSessionFactory的名称,不是引用--><propertyname="sqlSessionFactoryBeanName"value="sqlSessionFactory"/></bean><!--配置事务管理器--><beanid="transactionManager"class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><!--注入数据源--><propertyname="dataSource"ref="dataSource"/></bean><!--spring事务配置--><tx:adviceid="txAdvice"transaction-manager="transactionManager"><tx:attributes><!--DQL:查询操作,配置只读事务--><tx:methodname="get*"read-only="true"isolation="REPEATABLE_READ"propagation="REQUIRED"/><tx:methodname="find*"read-only="true"isolation="REPEATABLE_READ"propagation="REQUIRED"/><tx:methodname="select*"read-only="true"isolation="REPEATABLE_READ"propagation="REQUIRED"/><tx:methodname="query*"read-only="true"isolation="REPEATABLE_READ"propagation="REQUIRED"/><!--其他SQL:非只读事务--><tx:methodname="*"read-only="false"isolation="REPEATABLE_READ"propagation="REQUIRED"/></tx:attributes></tx:advice><!--配置AOP切入事务--><aop:config><!--切入点--><aop:pointcutid="pt"expression="execution(* com.sxt.service..*(..))"/><!--切面--><aop:advisoradvice-ref="txAdvice"pointcut-ref="pt"/></aop:config><importresource="classpath:springmvc.xml"/></beans>
相关实践学习
每个IT人都想学的“Web应用上云经典架构”实战
本实验从Web应用上云这个最基本的、最普遍的需求出发,帮助IT从业者们通过“阿里云Web应用上云解决方案”,了解一个企业级Web应用上云的常见架构,了解如何构建一个高可用、可扩展的企业级应用架构。
MySQL数据库入门学习
本课程通过最流行的开源数据库MySQL带你了解数据库的世界。 &nbsp; 相关的阿里云产品:云数据库RDS MySQL 版 阿里云关系型数据库RDS(Relational Database Service)是一种稳定可靠、可弹性伸缩的在线数据库服务,提供容灾、备份、恢复、迁移等方面的全套解决方案,彻底解决数据库运维的烦恼。 了解产品详情:&nbsp;https://www.aliyun.com/product/rds/mysql&nbsp;
目录
相关文章
|
7月前
|
XML Java 测试技术
《深入理解Spring》:IoC容器核心原理与实战
Spring IoC通过控制反转与依赖注入实现对象间的解耦,由容器统一管理Bean的生命周期与依赖关系。支持XML、注解和Java配置三种方式,结合作用域、条件化配置与循环依赖处理等机制,提升应用的可维护性与可测试性,是现代Java开发的核心基石。
|
7月前
|
前端开发 Java 微服务
《深入理解Spring》:Spring、Spring MVC与Spring Boot的深度解析
Spring Framework是Java生态的基石,提供IoC、AOP等核心功能;Spring MVC基于其构建,实现Web层MVC架构;Spring Boot则通过自动配置和内嵌服务器,极大简化了开发与部署。三者层层演进,Spring Boot并非替代,而是对前者的高效封装与增强,适用于微服务与快速开发,而深入理解Spring Framework有助于更好驾驭整体技术栈。
|
7月前
|
XML Java 应用服务中间件
【SpringBoot(一)】Spring的认知、容器功能讲解与自动装配原理的入门,带你熟悉Springboot中基本的注解使用
SpringBoot专栏开篇第一章,讲述认识SpringBoot、Bean容器功能的讲解、自动装配原理的入门,还有其他常用的Springboot注解!如果想要了解SpringBoot,那么就进来看看吧!
712 2
|
10月前
|
SQL Java 数据库连接
Spring、SpringMVC 与 MyBatis 核心知识点解析
我梳理的这些内容,涵盖了 Spring、SpringMVC 和 MyBatis 的核心知识点。 在 Spring 中,我了解到 IOC 是控制反转,把对象控制权交容器;DI 是依赖注入,有三种实现方式。Bean 有五种作用域,单例 bean 的线程安全问题及自动装配方式也清晰了。事务基于数据库和 AOP,有失效场景和七种传播行为。AOP 是面向切面编程,动态代理有 JDK 和 CGLIB 两种。 SpringMVC 的 11 步执行流程我烂熟于心,还有那些常用注解的用法。 MyBatis 里,#{} 和 ${} 的区别很关键,获取主键、处理字段与属性名不匹配的方法也掌握了。多表查询、动态
309 0
|
XML Java 数据格式
Spring IoC容器的设计与实现
Spring 是一个功能强大且模块化的 Java 开发框架,其核心架构围绕 IoC 容器、AOP、数据访问与集成、Web 层支持等展开。其中,`BeanFactory` 和 `ApplicationContext` 是 Spring 容器的核心组件,分别定位为基础容器和高级容器,前者提供轻量级的 Bean 管理,后者扩展了事件发布、国际化等功能。
332 18
|
XML Java 数据格式
京东一面:spring ioc容器本质是什么? ioc容器启动的步骤有哪些?
京东一面:spring ioc容器本质是什么? ioc容器启动的步骤有哪些?
|
XML Java 数据格式
Spring容器的本质
本文主要讨论Spring容器最核心的机制,用最少的代码讲清楚Spring容器的本质。
|
10月前
|
Java Spring 容器
SpringBoot自动配置的原理是什么?
Spring Boot自动配置核心在于@EnableAutoConfiguration注解,它通过@Import导入配置选择器,加载META-INF/spring.factories中定义的自动配置类。这些类根据@Conditional系列注解判断是否生效。但Spring Boot 3.0后已弃用spring.factories,改用新格式的.imports文件进行配置。
1347 0
|
11月前
|
人工智能 Java 测试技术
Spring Boot 集成 JUnit 单元测试
本文介绍了在Spring Boot中使用JUnit 5进行单元测试的常用方法与技巧,包括添加依赖、编写测试类、使用@SpringBootTest参数、自动装配测试模块(如JSON、MVC、WebFlux、JDBC等),以及@MockBean和@SpyBean的应用。内容实用,适合Java开发者参考学习。
1184 0