`MapperScannerConfigurer`是Spring与MyBatis集成时的一个关键组件,它用于自动扫描指定包下的Mapper接口并创建相应的代理对象

本文详细解析了SSM(Spring、SpringMVC、Mybatis)中MapperScannerConfigurer的使用,如何通过自动扫描配置,将Mapper接口生成代理并注入到Spring容器中。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

MapperScannerConfigurer是Spring与MyBatis集成时的一个关键组件,它用于自动扫描指定包下的Mapper接口并创建相应的代理对象。当你设置了<property name="basePackage" value="com.ssm.mapper">,它会查找以com.ssm.mapper开头的Java包中的Mapper接口。

然而,在你的配置中错误地使用了ref属性而不是value属性,应该是这样:

<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
    <property name="basePackage" value="com.ssm.mapper"/>
    <property name="sqlSessionFactory" ref="sqlSessionFactory"/>
</bean>

这里的ref="sqlSessionFactory"意味着sqlSessionFactory bean应该已经在应用上下文中存在并且是可注入的。正确的配置确保了Spring能够识别Mapper接口,扫描它们并将它们与SqlSessionFactory连接起来,以便在业务逻辑中通过接口调用执行SQL。
MapperScannerConfigurer 是 Spring Boot 中用于扫描和自动装配 MyBatis 映射器(Mapper)接口的一个工具类。它能够帮助管理 MyBatis 的全局配置,比如数据源(DataSource)、SqlSessionFactory 和 Mapper 接口的扫描范围。

当你在 Spring 容器中使用 @MapperScan 注解时,MapperScannerConfigurer 会自动检测是否有重复的 Mapper 接口定义。如果发现有两个或更多的 Mapper 类具有相同的完全限定名(即包名+类名),它会抛出错误,提示 “Bean already defined with the same name!”,这是为了避免在单个应用上下文中配置重复的 Mapper

为了避免这种重复,你应该确保每个 @MapperScan 注解指向不同的包,或者在其他配置中只使用一次 MapperScannerConfigurer。如果你使用了 MyBatis Plus,可能会因为其自身的配置导致冲突,这时可以考虑去掉其中不必要的 @MapperScan,让 Spring 自动扫描默认的包。

相关问题–:

  1. 如何在Spring Boot中手动配置MapperScannerConfigurer?

  2. 如果我想使用多个MapperScannerConfigurer,应该如何操作以防止冲突?

  3. 我如何知道哪个包应该在@MapperScan中指定?
    MapperScannerConfigurer是Spring与MyBatis集成过程中的一个重要工具,其主要作用是简化Mapper接口的管理。当配置这个组件时,你需要做以下几个步骤:

  4. 配置扫描范围: 在Spring配置文件中设置MapperScannerConfigurer,指定要扫描的包路径。这使得MyBatis能够自动找到该包内的Mapper接口。

    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="basePackage" value="com.example.mapper" />
    </bean>
    
  5. 自动代理生成: 当MapperScannerConfigurer扫描到Mapper接口时,它会动态地创建这些接口的代理实例。这是因为MyBatis的Mapper接口通常不直接暴露给Spring,而是通过代理机制来保证AOP(面向切面编程)的执行。

  6. 注入到Spring容器: 创建的代理对象会被Spring管理,并注入到需要的地方,如DAO层的Service中,方便后续调用Mapper的方法。

  7. 过滤选项: 如果需要,可以通过annotationClass属性指定特定的注解(如@Mapper),或使用markerInterface属性来限制扫描的接口类型。

    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="annotationClass" value="com.example.annotation.MyMapper" />
        <property name="markerInterface" value="com.example.base.BaseMapper" />
    </bean>
    

这样,无需手动为每个Mapper接口创建MapperFactoryBean,Spring会自动完成这个过程,提高了开发效率。
MapperScannerConfigurer避免扫描非Mapper接口的关键在于它只识别那些声明为接口的映射器。当配置这个Bean时,通过设置basePackage属性来指定要扫描的包名。basePackage通常包含了应用中所有Mapper接口定义的地方。

例如,在XML配置中,如引用[5]所示:

<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
    <property name="basePackage" value="org.mybatis.spring.sample.mapper" />
</bean>

这里的basePackage指定了org.mybatis.spring.sample.mapper下的所有包及其子包,Spring会自动查找这些包下声明为Mapper接口的类,并创建对应的代理实例注入到Spring容器中。由于接口的代理是在运行时动态生成的,所以只有接口类型的映射器才会被扫描和代理,而非具体实现类不会被错误地包括进来。

如果一个类实现了Mapper接口但不采用Mapper作为类名,按照MyBatis的默认扫描策略,它可能不会被自动扫描到。MyBatis通常是基于接口名称来查找与之相应的XML映射文件的,即期望接口名为UserMapper时,会去寻找UserMapper.xml文件。如果你的类命名为其他形式,比如CustomMapper,尽管它实现了Mapper接口,但由于名字不符合约定,mybatis可能会找不到对应的XML配置。

为了确保能被扫描,你需要按照以下一种或多种方式配置:

  1. 使用<package>标签,指定接口所在的包名,这样MyBatis会在该包及其子包下搜索接口及其对应XML:

    <mappers>
      <package name="your.package.name"/>
    </mappers>
    
  2. 明确指定每个<mapper>元素的class属性,即使类名非标准:

    <mappers>
      <mapper class="com.your.package.CustomMapper"/>
    </mappers>
    

然而,推荐的做法还是保持接口和XML文件的名称匹配,以便更直观地管理配置。

  • Mybatis MapperScannerConfigurer 自动扫描
    将Mapper接口生成代理注入到SpringMybatis在与Spring集成的时候可以配置MapperFactoryBean来生成Mapper接口的代理。
package com.ssm.chapter15.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.CookieValue;
import org.springframework.web.bind.annotation.RequestAttribute;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.SessionAttribute;
import org.springframework.web.bind.annotation.SessionAttributes;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.view.json.MappingJackson2JsonView;

import com.ssm.chapter15.pojo.Role;
import com.ssm.chapter15.service.RoleService;

@Controller
@RequestMapping("/attribute")
//可以配置数据模型的名称和类型,两者取或关系
@SessionAttributes(names ={
   "id"}, types = {
    Role.class })
public class AttributeController {
   
	
	@Autowired
	private RoleService roleService = null;
	
	@RequestMapping("/requestAttribute")
	public ModelAndView reqAttr(@RequestAttribute("id") Long id) {
   
		ModelAndView mv = new ModelAndView();
		Role role = roleService.getRole(id);
		mv.addObject("role", role);
		mv.setView(new MappingJackson2JsonView());
		return mv;
	}
	
	@RequestMapping("/sessionAttributes")
	public ModelAndView sessionAttrs(Long id) {
   
		ModelAndView mv = new ModelAndView();
		Role role = roleService.getRole(id);
        //根据类型,session将会保存角色信息
		mv.addObject("role", role); 
        //根据名称,session将会保存id
		mv.addObject("id", id);
        //视图名称,定义跳转到一个JSP文件上
		mv.setViewName("sessionAttribute");
		return mv;
	}
	
	@RequestMapping("/sessionAttribute")
	public ModelAndView sessionAttr(@SessionAttribute("id") Long id) {
   
		ModelAndView mv = new ModelAndView();
		Role role = roleService.getRole(id);
		mv.addObject("role", role);
		mv.setView(new MappingJackson2JsonView());
		return mv;
	}
	
	@RequestMapping("/getHeaderAndCookie")
	public String testHeaderAndCookie(
		@RequestHeader(value="User-Agent", required = false, defaultValue = "attribute")
	         String userAgent,
		@CookieValue(value = "JSESSIONID", required = true, defaultValue = "MyJsessionId") 
	         String jsessionId) {
   
		System.out.println("User-Agent:" + userAgent);
		System.out.println("JSESSIONID:" + jsessionId);
		return "index";
	}
}

package com.ssm.chapter15.controller;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.view.json.MappingJackson2JsonView;

import com.ssm.chapter15.pojo.Role;
import com.ssm.chapter15.pojo.RoleParams;
import com.ssm.chapter15.service.RoleService;

@Controller
@RequestMapping("/params")
public class ParamsController {
   
	
	@RequestMapping("/commonParams")
	public ModelAndView commonParams(String roleName, String note) {
   
	    System.out.println("roleName =>" + roleName);
	    System.out.println("note =>" + note);
	    ModelAndView mv = new ModelAndView();
	    mv.setViewName("index");
	    return mv;
	}
	
	@RequestMapping("/commonParamPojo")
	public ModelAndView commonParamPojo(RoleParams roleParams) {
   
	    System.out.println("roleName =>" + roleParams.getRoleName());
	    System.out.println("note =>" + roleParams.getNote());
	    ModelAndView mv = new ModelAndView();
	    mv.setViewName("index");
	    return mv;
	}
	
	@RequestMapping("/requestParam")
	//使用@RequestParam("role_name")指定映射HTTP参数名称
	public ModelAndView requestParam(@RequestParam("role_name") String roleName, String note) {
   
		System.out.println("roleName =>" + roleName);
	    System.out.println("note =>" + note);
		ModelAndView mv = new ModelAndView();
	    mv.setViewName("index");
	    return mv;
	}
	
	
	//注入角色服务对象
	@Autowired
	RoleService roleService;

	//{id}代表接收一个参数
	@RequestMapping("/getRole/{id}")
	//注解@PathVariable表示从URL的请求地址中获取参数
	public ModelAndView pathVariable(@PathVariable("id") Long id)  {
   
		Role role = roleService.getRole(id);
		ModelAndView mv = new ModelAndView();
		//绑定数据模型
		mv.addObject(role);
		//设置为JSON视图
		mv.setView(new MappingJackson2JsonView());
		return mv;
	}
	
	@RequestMapping("/findRoles")
	public ModelAndView findRoles(@RequestBody RoleParams roleParams) {
   
		List<Role> roleList = roleService.findRoles(roleParams);
		ModelAndView mv = new ModelAndView();
		//绑定模型
		mv.addObject(roleList);
		//设置为JSON视图
		mv.setView(new MappingJackson2JsonView());
		return mv;
	}
	
	@RequestMapping("/deleteRoles")
	public ModelAndView deleteRoles(@RequestBody List<Long> idList) {
   
		ModelAndView mv = new ModelAndView();
		//删除角色
		int total = roleService.deleteRoles(idList);
		//绑定视图
		mv.addObject("total", total);
		//JSON视图
	    mv.setView(new MappingJackson2JsonView());
		return mv;
	}
	
	@RequestMapping("/addRoles")
	public ModelAndView addRoles(@RequestBody List<Role> roleList) {
   
		ModelAndView mv = new ModelAndView();
		//删除角色
		int total = roleService.insertRoles(roleList);
		//绑定视图
		mv.addObject("total", total);
		//JSON视图
		mv.setView(new MappingJackson2JsonView());
		return mv;
	}
	
	@RequestMapping("/commonParamPojo2")
	public ModelAndView commonParamPojo2(String roleName, String note) {
   
		System.out.println("roleName =>" + roleName);
		System.out.println("note =>" + note);
		ModelAndView mv = new ModelAndView();
		mv.setViewName("index");
		return mv;
	}
	
}

package com.ssm.chapter15.controller;

import java.util.List;
import java.util.Map;

import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
import org.springframework.web.servlet.view.json.MappingJackson2JsonView;

import com.ssm.chapter15.pojo.PageParams;
import com.ssm.chapter15.pojo.Role;
import com.ssm.chapter15.pojo.RoleParams;
import com.ssm.chapter15.service.RoleService;
import com.ssm.chapter15.view.ExcelExportService;
import com.ssm.chapter15.view.ExcelView;


@Controller
@RequestMapping("/role")
public class RoleController {
   
	
	
	@Autowired
	private RoleService roleService = null; 
	
	@RequestMapping("/showRoleJsonInfo")
	public Model
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Bol5261

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值