mybatis - @MapperScan
一. 测试代码

//实体类
public class User {
private Integer id;
private String name;
private Integer age;
private String email;
private SexEnum sex;
//getter / setter
} public enum SexEnum { Male("Male", "男"), Female("Female", "女"); private String code; private String desc; SexEnum(String code, String desc){
this.code = code;
this.desc = desc;
}
} //Repository
@Repository
public interface UserMapper { public User getById(Integer id); public List<User> getByAge(Integer age); public int insert(User user);
} @SpringBootApplication
@MapperScan("com.study.demo.mybatis.mapper")
public class MybatisApplication {
public static void main(String[] args) {
SpringApplication.run(MybatisApplication.class, args);
}
} @Test
public void getById(){
System.out.println("getById 开始执行...");
User user = userMapper.getById(1);
System.out.println(user);
System.out.println("getById 结束执行...");
}
mapper.xml文件:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.study.demo.mybatis.mapper.UserMapper">
<insert id="insert">
insert into user (name,age,email,sex) values(#{name}, #{age}, #{email}, #{sex})
</insert> <select id="getById" resultType="com.study.demo.mybatis.vo.User">
select * from user where id = #{id}
</select> <select id="getByAge" resultType="com.study.demo.mybatis.vo.User">
select * from user where age = #{age}
</select>
</mapper>
配置文件:
spring:
datasource:
#type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost:3306/deco?characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull&allowMultiQueries=true&useSSL=false
username: root
password: 123456 mybatis:
mapper-locations: classpath:mapper/**Mapper.xml
@MapperScan("com.study.demo.mybatis.mapper") 主要做了两件事情:
1. 根据 "com.study.demo.mybatis.mapper" 配置进行mapper.java文件扫描.
此处扫描到的就是 SchoolMapper.java 和 UserMapper.java 两个文件
2. 为扫描到的文件进行 BeanDefinition 注册
//关键代码:
private void processBeanDefinitions(Set<BeanDefinitionHolder> beanDefinitions) {
GenericBeanDefinition definition;
for (BeanDefinitionHolder holder : beanDefinitions) {
definition = (GenericBeanDefinition) holder.getBeanDefinition(); if (logger.isDebugEnabled()) {
logger.debug("Creating MapperFactoryBean with name '" + holder.getBeanName()
+ "' and '" + definition.getBeanClassName() + "' mapperInterface");
} // the mapper interface is the original class of the bean
// but, the actual class of the bean is MapperFactoryBean
definition.getConstructorArgumentValues().addGenericArgumentValue(definition.getBeanClassName()); // issue #59
definition.setBeanClass(this.mapperFactoryBean.getClass());
......
}
在进入此方法之前, beanDefinitions 已经通过扫描得到,
| beanName | beanClass |
| schoolMapper | com.study.demo.mybatis.mapper.SchoolMapper |
| userMapper | com.study.demo.mybatis.mapper.UserMapper |
进入方法后, 会执行以下代码, 对 beanClass 进行重新赋值:
definition.setBeanClass(this.mapperFactoryBean.getClass());
这里的 mapperFactoryBean 是 ClassPathMapperScanner 的一个私有属性:
private MapperFactoryBean<?> mapperFactoryBean = new MapperFactoryBean<Object>();
也就是说, 后面对 beanName = userMapper 进行创建的时候, 会使用到 MapperFactoryBean
二. MapperFactoryBean
public class MapperFactoryBean<T> extends SqlSessionDaoSupport implements FactoryBean<T> {
private Class<T> mapperInterface;
private boolean addToConfig = true;
public MapperFactoryBean() {
//intentionally empty
}
public MapperFactoryBean(Class<T> mapperInterface) {
this.mapperInterface = mapperInterface;
}
/**
* {@inheritDoc}
*/
@Override
protected void checkDaoConfig() {
super.checkDaoConfig();
notNull(this.mapperInterface, "Property 'mapperInterface' is required");
Configuration configuration = getSqlSession().getConfiguration();
if (this.addToConfig && !configuration.hasMapper(this.mapperInterface)) {
try {
configuration.addMapper(this.mapperInterface);
} catch (Exception e) {
logger.error("Error while adding the mapper '" + this.mapperInterface + "' to configuration.", e);
throw new IllegalArgumentException(e);
} finally {
ErrorContext.instance().reset();
}
}
}
/**
* {@inheritDoc}
*/
@Override
public T getObject() throws Exception {
return getSqlSession().getMapper(this.mapperInterface);
}
/**
* {@inheritDoc}
*/
@Override
public Class<T> getObjectType() {
return this.mapperInterface;
}
/**
* {@inheritDoc}
*/
@Override
public boolean isSingleton() {
return true;
}
//------------- mutators --------------
/**
* Sets the mapper interface of the MyBatis mapper
*
* @param mapperInterface class of the interface
*/
public void setMapperInterface(Class<T> mapperInterface) {
this.mapperInterface = mapperInterface;
}
/**
* Return the mapper interface of the MyBatis mapper
*
* @return class of the interface
*/
public Class<T> getMapperInterface() {
return mapperInterface;
}
/**
* If addToConfig is false the mapper will not be added to MyBatis. This means
* it must have been included in mybatis-config.xml.
* <p/>
* If it is true, the mapper will be added to MyBatis in the case it is not already
* registered.
* <p/>
* By default addToCofig is true.
*
* @param addToConfig
*/
public void setAddToConfig(boolean addToConfig) {
this.addToConfig = addToConfig;
}
/**
* Return the flag for addition into MyBatis config.
*
* @return true if the mapper will be added to MyBatis in the case it is not already
* registered.
*/
public boolean isAddToConfig() {
return addToConfig;
}
}
从代码上看, 实现了 FactoryBean 接口, 他是一个 工厂bean.
在创建 userMapper 的时候, 就会调用 MapperFactoryBean 的 getObject() 方法.
md版本: https://files.cnblogs.com/files/elvinle/mybatis.zip
mybatis - @MapperScan的更多相关文章
- Mybatis——@MapperScan原理
@MapperScan配置在@Configuration注解的类上会导入MapperScannerRegistrar类. 而MapperScannerRegistrar实现了ImportBeanDef ...
- SpringBoot 使用yml配置 mybatis+pagehelper+druid+freemarker实例
SpringBoot 使用yml配置 mybatis+pagehelper+druid+freemarker实例 这是一个简单的SpringBoot整合实例 这里是项目的结构目录 首先是pom.xml ...
- Mybatis日志源码探究
一.项目搭建 1.pom.xml <dependencies> <dependency> <groupId>log4j</groupId> <ar ...
- springboot和mybatis集成
springboot和mybatis集成 pom <?xml version="1.0" encoding="UTF-8"?> <proje ...
- springboot与缓存(redis,或者caffeine,guava)
1.理论介绍 Java Caching定义了5个核心接口,分别是CachingProvider, CacheManager, Cache, Entry 和 Expiry. CachingProvide ...
- SpringBoot与Shiro的整合(单体式项目)
1.包结构 2.jar包,配置文件,类 2.1pom.xml文件配置 <?xml version="1.0" encoding="UTF-8"?> ...
- Spring IOC Container原理解析
Spring Framework 之 IOC IOC.DI基础概念 关于IOC和DI大家都不陌生,我们直接上martin fowler的原文,里面已经有DI的例子和spring的使用示例 <In ...
- Spring Boot MyBatis注解:@MapperScan和@Mapper
最近参与公司的新项目架构搭建,在使用mybatis的注解时,和同时有了不同意见,同事认为使用@Mapper注解简单明了,而我建议使用@MapperScan,直接将mapper所在的目录扫描进去就行,而 ...
- 启动类加注解@MapperScan spring boot mybatis 启动错误
Description: Field userDao in com.gcy.springsecuritydemo.service.user.UserService required a bean of ...
随机推荐
- Java输入和输出数组(加逗号)
输入示例 61,2,3,4,5,6 输出示例 1,2,3,4,5,61,2,3,4,5,6 import java.util.Scanner; public class Demo01 { public ...
- 使用css鼠标移动到图片放大效果
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"& ...
- ng-组件
几乎所有前端框架都在玩"组件化",而且最近都不约而同地选择了"标签化"这种思路,Angular 也不例外. 对新版本的 Angular 来说,一切都是围绕着&q ...
- linux 文件系统管理三部曲之三:挂载文件系统
linux 文件系统管理三部曲之一:磁盘分区 linux 文件系统管理三部曲之二:创建文件系统 上面说明了,硬盘的划分和格式化,那么怎么使用,还没说,这里说一下,怎么使用创建好的文件系统. 使用文件系 ...
- Oracle中表与包体用户没有操作权限问题
一.表1.在stg用户下查看table_name 表是否存在select * from table_name 2 在表所在用户执行(授权)grant select,update on table_na ...
- 数据库SQL语法到MySQL实操
一.基础 1.说明:创建数据库CREATE DATABASE database-name 2.说明:删除数据库drop database dbname 3.说明:备份sql server--- 创建 ...
- Power Strings[poj2406]题解
Power Strings Description - Given two strings a and b we define ab to be their concatenation. For ex ...
- prach定点化处理
- 剑指offer 56.删除有序链表中的重复结点
56. 删除有序链表中的重复结点 题目描述 在一个排序的链表中,存在重复的结点,请删除该链表中重复的结点,重复的结点不保留,返回链表头指针. 例如,链表1->2->3->3-> ...
- PYthon之路Day12
生成器 核心:生成器的本质就是一个迭代器 程序员自己写的一种迭代器 作用:节省空间 生成器可以使用for进行遍历 生成器编写方式: 基于函数编写 def func(): print('这是一个函 ...