全部学科
NodeJS全栈
nodejs
Python全栈
python
小程序首页
📅 2026-05-20 6 分钟 ✍️ juanwangdev

Mapper 接口注入

Mapper 接口注入是 Spring-MyBatis 集成的核心机制,通过动态代理将接口转换为可执行的 SQL 操作。

@MapperScan 注解

@MapperScan 用于自动扫描并注册 Mapper 接口为 Spring Bean。

Java
@Configuration
@MapperScan("com.example.mapper")
public class MyBatisConfig {
}

多包扫描

Java
@MapperScan({"com.example.mapper.user", "com.example.mapper.order"})

指定 SqlSessionFactory

Java
// 多数据源时必须指定
@MapperScan(basePackages = "com.example.mapper", 
            sqlSessionFactoryRef = "sqlSessionFactory")
属性说明
basePackages扫描包路径,支持多个
basePackageClasses类型安全的包路径(以某个类所在包为准)
sqlSessionFactoryRef指定 SqlSessionFactory Bean 名称
sqlSessionTemplateRef指定 SqlSessionTemplate Bean 名称
annotationClass只注册带有该注解的接口
markerInterface只注册实现该接口的接口

注入 Mapper

Java
@Service
public class UserService {

    @Autowired
    private UserMapper userMapper;

    public User findById(Long id) {
        return userMapper.selectById(id);
    }
}

也可使用构造器注入(推荐):

Java
@Service
@RequiredArgsConstructor
public class UserService {

    private final UserMapper userMapper;

    public User findById(Long id) {
        return userMapper.selectById(id);
    }
}

接口代理创建原理

Mapper 接口本身没有实现类,通过 JDK 动态代理创建代理对象:

Java
@MapperScan 扫描
    |
    v
MapperScannerConfigurer
    |
    v
MapperFactoryBean (每个 Mapper 对应一个)
    |
    v
getObject() 返回代理对象
    |
    v
MapperProxyFactory 创建 MapperProxy
    |
    v
JDK 动态代理 (InvocationHandler)
    |
    v
方法调用时解析 @Select/@Insert 或 XML 中的 SQL
    |
    v
通过 SqlSession 执行

Mapper 代理底层使用 JDK 动态代理,因此 Mapper 接口必须是 interface,不能是 class。

MapperFactoryBean

每个 Mapper 接口对应一个 MapperFactoryBean:

Java
// 内部逻辑简化
public class MapperFactoryBean<T> implements FactoryBean<T> {
    
    public T getObject() {
        return getSqlSession().getMapper(mapperInterface);
    }
    
    public Class<T> getObjectType() {
        return mapperInterface;
    }
}

注意事项

Java
// 错误:Mapper 不是 Spring Bean,无法注入
public class UserService {
    private UserMapper userMapper = new UserMapper();  // 错误
}

// 错误:包路径不匹配,@MapperScan 未扫描到
@MapperScan("com.example.dao")  // 实际 Mapper 在 com.example.mapper
public class Config { }

// 正确:确保扫描路径正确
@MapperScan("com.example.mapper")
public class Config { }

Mapper 注入失败通常是 @MapperScan 路径配置错误或未添加该注解。

与 @Mapper 注解的区别

方式说明适用场景
@MapperScan批量扫描注册项目级配置,推荐
@Mapper单个接口标记少量 Mapper 或分布式模块
text
// 不使用 @MapperScan 时,在每个接口上标记 @Mapper
@Mapper
public interface UserMapper {
    User selectById(Long id);
}

要点总结

  • @MapperScan 批量扫描 Mapper 接口并注册为 Spring Bean
  • 通过 @Autowired 或构造器注入 Mapper 代理对象
  • Mapper 代理通过 JDK 动态代理实现,接口必须有 interface
  • 多数据源时需通过 sqlSessionFactoryRef 指定对应工厂
  • MapperFactoryBean 为每个接口创建代理,getObject() 返回代理实例
  • @MapperScan 推荐项目级使用,@Mapper 适合单个接口标记

📝 发现内容有误?点击此处直接编辑

← 上一篇 @SelectProvider 动态 SQL
下一篇 → Spring-MyBatis 集成
想查看更多题目和详细解析?
小程序提供完整的题库、模拟考试和详细解析
马上就来

长按或扫描二维码,立即体验

扫码体验小程序
马上就来
使用微信扫描二维码
立即体验完整题库