Mybatis Mapper Bean 生成源码分析一

简介: Mybatis Mapper Bean 生成源码分析一

Mybatis Mapper Bean 生成源码分析一

问题

我们的Mapper接口,用的是@Mapper,而非@Service等会被Spring扫描的注解,那么它最后怎么会生成一个Bean呢。

重点方法一:ClassPathMapperScanner#doScan

org.mybatis.spring.mapper.ClassPathMapperScanner继承自org.springframework.context.annotation.ClassPathBeanDefinitionScanner,重载了其#doScan方法,调用其父类进行包下的扫描,再对扫描出来的BeanDefinitionHolder beanDefinitions 进行处理,代码如下:

/**
   * Calls the parent search that will search and register all the candidates. Then the registered objects are post
   * processed to set them as MapperFactoryBeans
   */
  @Override
  public Set<BeanDefinitionHolder> doScan(String... basePackages) {
    // 让Spring的父类负责扫描
    Set<BeanDefinitionHolder> beanDefinitions = super.doScan(basePackages);
    if (beanDefinitions.isEmpty()) {
      LOGGER.warn(() -> "No MyBatis mapper was found in '" + Arrays.toString(basePackages)
          + "' package. Please check your configuration.");
    } else {
      // mybatis 定制,修改了bean 定义
      processBeanDefinitions(beanDefinitions);
    }
    return beanDefinitions;
  }

重点方法二:ClassPathMapperScanner#processBeanDefinitions

private Class<? extends MapperFactoryBean> mapperFactoryBeanClass = MapperFactoryBean.class;
private void processBeanDefinitions(Set<BeanDefinitionHolder> beanDefinitions) {
    GenericBeanDefinition definition;
    for (BeanDefinitionHolder holder : beanDefinitions) {
      definition = (GenericBeanDefinition) holder.getBeanDefinition();
      String beanClassName = definition.getBeanClassName();
      // the mapper interface is the original class of the bean
      // but, the actual class of the bean is MapperFactoryBean
      definition.getConstructorArgumentValues().addGenericArgumentValue(beanClassName); 
      // 替换成了MapperFactoryBean,一个FactoryBean,在Bean真正产生时用来创建Bean的工厂
      definition.setBeanClass(this.mapperFactoryBeanClass);
    }
}

总结

mybatis通过扩展doScan方法,将扫描到的Mapper的BeanDefinitionHolder中的beanClass从接口,改成了MapperFactoryBean,完成了这波偷天换日的第一步,之后Bean的初始化时,最终将通过MapperFactoryBean扩展的FactoryBean 的 getObject方法返回真正的Mapper(JDK 代理)。

目录
相关文章
|
8天前
|
XML Java 数据库连接
Mybatis 模块拆份带来的 Mapper 扫描问题
Mybatis 模块拆份带来的 Mapper 扫描问题
14 0
|
1月前
|
SQL
自定义SQL,可以利用MyBatisPlus的Wrapper来构建复杂的Where条件,如何自定义SQL呢?利用MyBatisPlus的Wrapper来构建Wh,在mapper方法参数中用Param注
自定义SQL,可以利用MyBatisPlus的Wrapper来构建复杂的Where条件,如何自定义SQL呢?利用MyBatisPlus的Wrapper来构建Wh,在mapper方法参数中用Param注
|
1月前
|
Java 数据库连接 mybatis
SpringBoot配置Mybatis注意事项,mappers层下的name命名空间,要落实到Dao的video类,resultType要落到bean,配置好mybatis的对应依赖。
SpringBoot配置Mybatis注意事项,mappers层下的name命名空间,要落实到Dao的video类,resultType要落到bean,配置好mybatis的对应依赖。
|
1月前
|
Java 数据库连接 Maven
Private method ‘getVideoList()‘ is never used,mybatis必须指定Mapper文件和实体目录,在参考其他人写的代码,要认真分析别人的代码,不要丢失
Private method ‘getVideoList()‘ is never used,mybatis必须指定Mapper文件和实体目录,在参考其他人写的代码,要认真分析别人的代码,不要丢失
|
2月前
|
SQL Java 数据库连接
Mybatis如何使用mapper代理开发
Mybatis如何使用mapper代理开发
|
2月前
|
XML 关系型数据库 数据库
使用mybatis-generator插件生成postgresql数据库model、mapper、xml
使用mybatis-generator插件生成postgresql数据库model、mapper、xml
142 0
|
2月前
|
SQL Java 数据库连接
Mybatis中一对多mapper配置
Mybatis中一对多mapper配置
23 0
|
3月前
|
XML Java 数据库连接
Mybatis逆向工程的2种方法,一键高效快速生成Pojo、Mapper、XML,摆脱大量重复开发
【5月更文挑战第10天】Mybatis逆向工程的2种方法,一键高效快速生成Pojo、Mapper、XML,摆脱大量重复开发
44 6
|
2月前
|
Java 数据库连接 mybatis
Mybatis mapper动态代理解决方案
该文介绍了Mybatis中使用Mapper接口的方式代替XML配置执行SQL。Mapper接口规范包括:namespace与接口类路径相同,select ID与接口方法名一致,parameterType和方法参数类型匹配,resultType与返回值类型一致。实现过程中,需配置Mapper.xml,编写Mapper.java接口,并在Mybatis-config.xml中设置。测试类中,通过SqlSession的getMapper方法获取接口的动态代理对象,调用方法执行SQL。
|
2月前
|
Java 数据库连接 mybatis
为什么Mybatis Mapper不需要实现类?
在学习Java动态代理之前,我想让大家先思考这样几个问题。 • JDK动态代理为什么不能对类进行代理? • Mybatis Mapper接口为什么不需要实现类? 如果你还不知道上述问题的答案,那么这篇文章一定能消除你心中的疑惑。