编程语言
首页 > 编程语言> > 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 代理)。

标签:Mapper,MapperFactoryBean,definition,beanDefinitions,Bean,源码,doScan
来源: https://blog.csdn.net/a17816876003/article/details/120251684