Java教程

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 代理)。

这篇关于Mybatis Mapper Bean 生成源码分析一的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!