mybatis - @MapperScan

一. 测试代码

mybatis - @MapperScan_第1张图片

 

 

//实体类
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 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 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(); 
 

也就是说, 后面对 beanName = userMapper 进行创建的时候, 会使用到  MapperFactoryBean

 

二. MapperFactoryBean

public class MapperFactoryBean extends SqlSessionDaoSupport implements FactoryBean {

  private Class mapperInterface;

  private boolean addToConfig = true;

  public MapperFactoryBean() {
    //intentionally empty 
  }
  
  public MapperFactoryBean(Class 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 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 mapperInterface) {
    this.mapperInterface = mapperInterface;
  }

  /**
   * Return the mapper interface of the MyBatis mapper
   *
   * @return class of the interface
   */
  public Class 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.
   * 

* If it is true, the mapper will be added to MyBatis in the case it is not already * registered. *

* 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)