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 ...
随机推荐
- ex03
1. a heuristic function h(n): a heuristic value of n, that is the estimated cost of reaching goal fr ...
- MVC5+EF6 入门完整教程八:数据迁移
https://www.cnblogs.com/miro/p/4164076.html
- Oracle Solaris 10 重启后提示 Bad PBR sig
Solaris 10 安装完毕重启后提示 Bad PBR sig 在磁盘分区的时候,默认自带的 overlap 不要删除,否则启动报错. 分区时,保留overlap(默认显示总容量大小)分区.安装操作 ...
- phpstudy+phpstorm 浏览器没有解析php文件,直接显示源码
用phpstorm编辑完项目,右键浏览器预览时页面报错:502 Bad Gateway PhpStorm 2019.1 此时默认打开的地址是:localhost:63339/开头的一长串…… 查资料说 ...
- DirectX11--HLSL语法入门
前言 编写本内容仅仅是为了完善当前的教程体系,入门级别的内容其实基本上都是千篇一律,仅有一些必要细节上的扩充.要入门HLSL,只是掌握入门语法,即便把HLSL的全部语法也吃透了也并不代表你就能着色器代 ...
- [POI2015]PUS [线段树优化建图]
problem 线段树优化建图,拓扑,没了. #include <bits/stdc++.h> #define ls(x) ch[x][0] #define rs(x) ch[x][1] ...
- yii2 插件使用
GridView插件 行内文本编辑 后端 if (Yii::$app->request->post('hasEditable')) { $id = Yii::$app->reques ...
- 曼孚科技:AI领域3种典型的深度学习算法
深度学习(Deep Learning)是机器学习(Machine Learning)领域中一个新的研究方向,引领了第三次人工智能的浪潮. 本文整理了深度学习领域3种典型的算法,希望可以帮助大家更好地 ...
- Alice and Hairdresser
Alice's hair is growing by leaps and bounds. Maybe the cause of it is the excess of vitamins, or may ...
- clone()与clone(true)的用法
clone() 方法生成被选元素的副本,包含子节点.文本和属性. 使用 clone(true) 方法在clone()的基础上还包括克隆元素的事件处理器.