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 ...
随机推荐
- 【新人赛】阿里云恶意程序检测 -- 实践记录10.20 - 数据预处理 / 训练数据分析 / TF-IDF模型调参
Colab连接与数据预处理 Colab连接方法见上一篇博客 数据预处理: import pandas as pd import pickle import numpy as np # 训练数据和测试数 ...
- MY_0003:设置界面显示单位
1,设置单位
- 如何使用GitHub中和别人合作开发一个项目
第一步:找到别人在GitHub的项目,点击Fork跳转到自己的GitHub 第二步:跳转到自己页面后进行克隆下载 第三步:在自己的idea中修改完毕后,进行推送将自己GitHub的项目进行修改 第四步 ...
- 免费生成二维码接口,可直接嵌入到web项目中,附带嵌入方法,任意颜色二维码,任意大小二维码!
在线体验连接:http://www.zhaimaojun.top/qrcode/ 你是否在项目中寻找方便而且免费的可以直接嵌入到项目中的二维码生成工具呢?你找到了这里,说明你已经找到了!不要犹豫直接拿 ...
- 【转】Servlet 九大对象和四个作用域
隐式对象 说明 request 转译后对应HttpServletRequest/ServletRequest对象 response 转译后对应HttpServletRespons/ServletRes ...
- maven发布java-分支构建
1.安装parameter插件 2. 新建maven项目 3.配置maven项目 4.配置maven项目2 5.配置maven项目3 6. 模拟开发给提交打tag标签 7.版本发布 8.tag获取并构 ...
- processing data
获取有效数据 Scikit-learn will not accept categorical features by default API里面不知使用默认的特征变量名,因此需要编码 这里我还是有疑 ...
- svn error: "Previous operation has not finished; run 'cleanup' if it was interrupted"
出现这种问题,有几个原因 1.本身文件确实是锁住了 2.之前clean up 过很多次,但是每次都可能以失败告终,造成work queue存在缓存队列 3.svn lock 有lock记录 以下是简单 ...
- python3练习100题——004
继续做题-经过python3的测试 原题链接:http://www.runoob.com/python/python-exercise-example4.html 题目:输入某年某月某日,判断这一天是 ...
- springboot~集成DataSource 与 Druid监控配置
介绍 Druid首先是一个数据库连接池.Druid是目前最好的数据库连接池,在功能.性能.扩展性方面,都超过其他数据库连接池,Druid已经在阿里巴巴部署了超过600个应用,经过一年多生产环境大规模部 ...