源码-mybatis-spring:2.0.4

1、前言

主要是MapperScannerConfigurer类,这是一个后置处理器,用于后置处理beanDefinition,这个类在bean开始创建之前将扫描到的mapper的beanDefinition的beanClass属性替换为MapperFactoryBean类,beanName还是mapper的name。spring创建类是根据beanDefinition定义的beanClass属性来反射创建对象的。然后以(beanName:根据beanClass创建的对象)为key和value对,放入singletonObjects中。

此时singletonObjects中放的是正常的mapper的beanName(即xxxMapper)和MapperFactoryBean实例

在注入mapper属性时,如果根据mapper的beanDefinition判断是FactoryBean类型,那么调用对应的FactoryBean单例对象的getObject方法,并将结果注入mapper。

MapperFactoryBean间接实现了InitializingBean接口,在接口方法中addMapper

而MapperFactoryBean的getObject方法为

public T getObject() throws Exception {
  return getSqlSession().getMapper(this.mapperInterface);
}

如上,最终调用的sqlsessionTemplate.getMapper方法。最终会调用MapperRegistry.getMapper方法。

2、@MapperScan注解

我们在启动类上加@MapperScanner注解,而@MapperScanner注解上方有@Import注解,此注解在ConfigurationClassPostProcessor后置处理器的后置处理方法中被解析,将@Import注解引入的类包装成BeanDefinition注册到spring

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@Import(MapperScannerRegistrar.class)
@Repeatable(MapperScans.class)
public @interface MapperScan {
	// ...
}

3、MapperScannerRegistrar

@MapperScanner注解引入了MapperScannerRegistrar类,此类实现了ImportBeanDefinitionRegistrar接口,解析阶段会调用registerBeanDefinitions方法。
registerBeanDefinitions方法会为MapperScannerConfigurer类生成BeanDefintion并注入spring。

public class MapperScannerRegistrar implements ImportBeanDefinitionRegistrar, ResourceLoaderAware {

  /**
   * {@inheritDoc}
   * 
   * @deprecated Since 2.0.2, this method not used never.
   */
  @Override
  @Deprecated
  public void setResourceLoader(ResourceLoader resourceLoader) {
    // NOP
  }

  /**
   * {@inheritDoc}
   */
  @Override
  public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
    AnnotationAttributes mapperScanAttrs = AnnotationAttributes
        .fromMap(importingClassMetadata.getAnnotationAttributes(MapperScan.class.getName()));
    if (mapperScanAttrs != null) {
      registerBeanDefinitions(importingClassMetadata, mapperScanAttrs, registry,
          generateBaseBeanName(importingClassMetadata, 0));
    }
  }
  // 生成MapperScannerConfigurer的BeanDefinition并注入spring
  void registerBeanDefinitions(AnnotationMetadata annoMeta, AnnotationAttributes annoAttrs,
      BeanDefinitionRegistry registry, String beanName) {

    BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(MapperScannerConfigurer.class);
    builder.addPropertyValue("processPropertyPlaceHolders", true);

    Class<? extends Annotation> annotationClass = annoAttrs.getClass("annotationClass");
      // 此属性一般为Mapper注解
    if (!Annotation.class.equals(annotationClass)) {
      builder.addPropertyValue("annotationClass", annotationClass);
    }

    Class<?> markerInterface = annoAttrs.getClass("markerInterface");
    if (!Class.class.equals(markerInterface)) {
      builder.addPropertyValue("markerInterface", markerInterface);
    }

    Class<? extends BeanNameGenerator> generatorClass = annoAttrs.getClass("nameGenerator");
    if (!BeanNameGenerator.class.equals(generatorClass)) {
      builder.addPropertyValue("nameGenerator", BeanUtils.instantiateClass(generatorClass));
    }

    Class<? extends MapperFactoryBean> mapperFactoryBeanClass = annoAttrs.getClass("factoryBean");
    if (!MapperFactoryBean.class.equals(mapperFactoryBeanClass)) {
      builder.addPropertyValue("mapperFactoryBeanClass", mapperFactoryBeanClass);
    }

    String sqlSessionTemplateRef = annoAttrs.getString("sqlSessionTemplateRef");
    if (StringUtils.hasText(sqlSessionTemplateRef)) {
      builder.addPropertyValue("sqlSessionTemplateBeanName", annoAttrs.getString("sqlSessionTemplateRef"));
    }

    String sqlSessionFactoryRef = annoAttrs.getString("sqlSessionFactoryRef");
    if (StringUtils.hasText(sqlSessionFactoryRef)) {
      builder.addPropertyValue("sqlSessionFactoryBeanName", annoAttrs.getString("sqlSessionFactoryRef"));
    }

    List<String> basePackages = new ArrayList<>();
    basePackages.addAll(
        Arrays.stream(annoAttrs.getStringArray("value")).filter(StringUtils::hasText).collect(Collectors.toList()));
	// Mapper的位置
    basePackages.addAll(Arrays.stream(annoAttrs.getStringArray("basePackages")).filter(StringUtils::hasText)
        .collect(Collectors.toList()));
	// 以类的形式表达Mapper的位置,比如我们将一个com.demo.mapper.XXXPackage类标注basePackageClasses属性,
    // 么会截取com.demo.mapper作为mapper的位置
    basePackages.addAll(Arrays.stream(annoAttrs.getClassArray("basePackageClasses")).map(ClassUtils::getPackageName)
        .collect(Collectors.toList()));
	// 如果没有上面俩个属性,那么默认拿含有@MapperScanner注解的类所在包作为Mapper位置。
    if (basePackages.isEmpty()) {
      basePackages.add(getDefaultBasePackage(annoMeta));
    }

    String lazyInitialization = annoAttrs.getString("lazyInitialization");
    if (StringUtils.hasText(lazyInitialization)) {
      builder.addPropertyValue("lazyInitialization", lazyInitialization);
    }
	
    builder.addPropertyValue("basePackage", StringUtils.collectionToCommaDelimitedString(basePackages));

    registry.registerBeanDefinition(beanName, builder.getBeanDefinition());

  }
  // ...
}

4、MapperScannerConfigurer

MapperScannerConfigurer实现了BeanDefinitionRegistryPostProcessor接口,在上面的MapperScannerRegistrar类的registerBeanDefinitions方法执行完以后,MapperScannerConfigurer的BeanDefinition就被注册到了spring,在refresh方法中的invokeBeanFactoryPostProcessors阶段被调用其postProcessBeanDefinitionRegistry方法。

public class MapperScannerConfigurer
    implements BeanDefinitionRegistryPostProcessor, InitializingBean, ApplicationContextAware, BeanNameAware {
    // ...
    
    // 在BeanDefinitionRegistryPostProcessor后置方法中扫描所有mapper的beanDefinition,
    // 并将其beanClass替换为MapperFactoryBean
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
    if (this.processPropertyPlaceHolders) {
      processPropertyPlaceHolders();
    }
	// ClassPathMapperScanner继承并重写了doScan方法
    ClassPathMapperScanner scanner = new ClassPathMapperScanner(registry);
    scanner.setAddToConfig(this.addToConfig);
    scanner.setAnnotationClass(this.annotationClass);
    scanner.setMarkerInterface(this.markerInterface);
    scanner.setSqlSessionFactory(this.sqlSessionFactory);
    scanner.setSqlSessionTemplate(this.sqlSessionTemplate);
    scanner.setSqlSessionFactoryBeanName(this.sqlSessionFactoryBeanName);
    scanner.setSqlSessionTemplateBeanName(this.sqlSessionTemplateBeanName);
    scanner.setResourceLoader(this.applicationContext);
    scanner.setBeanNameGenerator(this.nameGenerator);
    scanner.setMapperFactoryBeanClass(this.mapperFactoryBeanClass);
    if (StringUtils.hasText(lazyInitialization)) {
      scanner.setLazyInitialization(Boolean.valueOf(lazyInitialization));
    }
    scanner.registerFilters();
    scanner.scan(
        StringUtils.tokenizeToStringArray(this.basePackage, ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS));
  }
    
    
  //...
}

5、ClassPathMapperScanner

ClassPathMapperScanner,扫描所有mapper的beanDefinition,并将其beanClass替换为MapperFactoryBean,这样我们在Service中@Autowired我们的mapper时候,其实是将MapperFactoryBean.getObject()方法的返回设置为mapper属性。

public class ClassPathMapperScanner extends ClassPathBeanDefinitionScanner {
    // ...
    
    public Set<BeanDefinitionHolder> doScan(String... basePackages) {
      // 这里扫描的是所有的Mapper
      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 {
        processBeanDefinitions(beanDefinitions);
      }

      return beanDefinitions;
    }
    
    // 偷天换日,将mapper对应beanDefinition的beanClass属性替换为MapperFactoryBean.class
    private void processBeanDefinitions(Set<BeanDefinitionHolder> beanDefinitions) {
        GenericBeanDefinition definition;
        for (BeanDefinitionHolder holder : beanDefinitions) {
          definition = (GenericBeanDefinition) holder.getBeanDefinition();
          String beanClassName = definition.getBeanClassName();
          LOGGER.debug(() -> "Creating MapperFactoryBean with name '" + holder.getBeanName() + "' and '" + beanClassName
              + "' mapperInterface");

          // the mapper interface is the original class of the bean
          // but, the actual class of the bean is MapperFactoryBean
          definition.getConstructorArgumentValues().addGenericArgumentValue(beanClassName); // issue #59
          // 将代表Mapper的Class换成MapperFactoryBean.class,这样在我们@Autowired一个Mapper的时候,实际上获取的是
          // MapperFactoryBean.getObject()的结果
          definition.setBeanClass(this.mapperFactoryBeanClass);
		  // 为MapperFactoryBean设置addToConfig属性
          definition.getPropertyValues().add("addToConfig", this.addToConfig);
          // 为MapperFactoryBean设置sqlSessionFactory属性
          boolean explicitFactoryUsed = false;
          if (StringUtils.hasText(this.sqlSessionFactoryBeanName)) {
            definition.getPropertyValues().add("sqlSessionFactory",
                new RuntimeBeanReference(this.sqlSessionFactoryBeanName));
            explicitFactoryUsed = true;
          } else if (this.sqlSessionFactory != null) {
            definition.getPropertyValues().add("sqlSessionFactory", this.sqlSessionFactory);
            explicitFactoryUsed = true;
          }
		  // 为MapperFactoryBean设置sqlSessionTemplate属性
          if (StringUtils.hasText(this.sqlSessionTemplateBeanName)) {
            if (explicitFactoryUsed) {
              LOGGER.warn(
                  () -> "Cannot use both: sqlSessionTemplate and sqlSessionFactory together. sqlSessionFactory is ignored.");
            }
            definition.getPropertyValues().add("sqlSessionTemplate",
                new RuntimeBeanReference(this.sqlSessionTemplateBeanName));
            explicitFactoryUsed = true;
          } else if (this.sqlSessionTemplate != null) {
            if (explicitFactoryUsed) {
              LOGGER.warn(
                  () -> "Cannot use both: sqlSessionTemplate and sqlSessionFactory together. sqlSessionFactory is ignored.");
            }
            definition.getPropertyValues().add("sqlSessionTemplate", this.sqlSessionTemplate);
            explicitFactoryUsed = true;
          }
		  // 如果没有sqlSessionTemplate属性或者sqlSessionFactory属性,那么就使用spring的AUTOWIRE_BY_TYPE进行属性注入
          // spring注入的时候会遍历属性的set方法,如果有set方法并且不是set基础类型那么就会从容器中获取set方法参数类型的bean进行属性注入
          if (!explicitFactoryUsed) {
            LOGGER.debug(() -> "Enabling autowire by type for MapperFactoryBean with name '" + holder.getBeanName() + "'.");
            definition.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_BY_TYPE);
          }
          definition.setLazyInit(lazyInitialization);
        }
     }
  
  // ...
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值