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 ...
随机推荐
- Spark学习之路 (七)Spark 运行流程[转]
Spark中的基本概念 (1)Application:表示你的应用程序 (2)Driver:表示main()函数,创建SparkContext.由SparkContext负责与ClusterManag ...
- Open Live Writer(olw)博客写作软件
前言 wlw似乎不再提供下载了,从微软的官网下载安装程序之后,无法联网下载olw组件,所以写博客改用olw. olw是wlw的开源版本,所以wlw上的操作是可以在olw上继续使用的. 关于wlw的知识 ...
- 使用微信扫一扫时获取sign签名
private $appId = '你的APPID'; private $appSecret = '你的APPsecret'; /** * 获取签名信息 * @return array */ publ ...
- hdu 1005 Number Sequence(循环节)
题意,f(1)=1,f(2)=1,f(n)=a*f(n-1)+b*f(n-2),求f(n)%7 这个题可能数据不够严谨,所以有些错误的做法也可以通过,比如7 7 50,应该输出0而不是1 解:找到关键 ...
- PAT (Advanced Level) Practice 1035 Password (20 分)
To prepare for PAT, the judge sometimes has to generate random passwords for the users. The problem ...
- 《NVM-Express-1_4-2019.06.10-Ratified》学习笔记(6.5-加-8.2-加-8.3)End-to-end_Data_Protection
6.5 End-to-end Protection Information 端到端保护信息 包含数据转存的命令可以使用端到端数据保护.在这些命令内部[位于Command Dword 12 的 [29: ...
- 记PHP使用rtrim()导致获得的数据乱码问题
一.问题描述: 我用rtrim()函数去除右侧多余的"."号,去除之后,发现乱码. 二.出现原因: 当右侧没有分号,要去除的字符串的十六进制又刚刚好以81结尾,就导致81被去除,从 ...
- Python 3.9.0 首个迭代版本发布了
Python 3.9.0 alpha 1 发布了,这是 3.8 之后的首个 3.9 系列版本. ! 官方没有介绍新特性,也没有添加新模块,但是以下模块有所改进: ast asyncio curses ...
- mysql之数据初始化update操作
1.单表的:update user set name = (select name from user where id in (select id from user where name='小苏' ...
- ubuntu set up 4 - 设置和软件
1. Top Bar显示日期 https://askubuntu.com/questions/966576/customizing-tray-taskbar-date-display-in-ubunt ...