关于java:MyBatis-学习笔记Mapper扫描

45次阅读

共计 18612 个字符,预计需要花费 47 分钟才能阅读完成。

Mapper 扫描须要依赖 Maybtis/Spring 这个我的项目,官网文档:
https://mybatis.org/spring/zh/index.html

Mapper 扫描依赖两种形式:

  1. 通过 @Mapper 注解 (想通过该注解实现扫描 Mapper,须要依赖 mybatis/spring-boot-starter 这个我的项目)
  2. 通过 @MapperScan 注解

无论是 @Mapper 还是 @MapeprScan 注解,底层都是须要去注册一个 MapperScannerConfigurer 的 Bean , 而后通过该 Bean 来实现 Mapper 的被动注入。

@Mapper 注解

@Mapper 注解次要应用在 Mapper 接口上,如果要实现只对 @Mapper 注解的接口实现扫描,则须要引入 mybatis/spring-boot-starter 这个我的项目。
mybatis/spring-boot-starter 应用办法请参考:https://github.com/mybatis/spring-boot-starter/blob/master/mybatis-spring-boot-autoconfigure/src/site/zh/markdown/index.md
AutoConfiguredMapperScannerRegistrar 则是主动扫描 @Mapper 注解接口的实现类。
然而该类启用的条件,必须是 Spring 没有找到 MapperScannerConfigurerMapperFactoryBean 的 bean。

源码剖析

AutoConfiguredMapperScannerRegistrarMybatisAutoConfiguration 的动态外部类,故这里展现的是 MybatisAutoConfiguration 的源码。

/**
* MybatisAutoConfiguration 是一个配置类 
* 启用该配置类须要我的项目存在 SqlSessionFactory 和 SqlSessionFactoryBean 这两个类(这两个类都在 mybatis/spring 我的项目中 )
* mybatis/spring-boot-starter 会主动引入 mybatis/spring
*/
@org.springframework.context.annotation.Configuration(proxyBeanMethods = false)
@ConditionalOnClass({SqlSessionFactory.class, SqlSessionFactoryBean.class})
@ConditionalOnSingleCandidate(DataSource.class)
@EnableConfigurationProperties(MybatisProperties.class)
@AutoConfigureAfter({DataSourceAutoConfiguration.class, MybatisLanguageDriverAutoConfiguration.class})
public class MybatisAutoConfiguration implements InitializingBean {
  // 疏忽局部源码,这里只展现要探讨的局部

  /**
  * 对 @Mapper 注解主动扫描的实现类
  * 它继承了 ImportBeanDefinitionRegistrar 接口,实现了 registerBeanDefinitions() 办法
  * registerBeanDefinitions() 办法次要是创立并注册 MapperScannerConfigurer 的 BeanDefinition
  */
  public static class AutoConfiguredMapperScannerRegistrar
      implements BeanFactoryAware, EnvironmentAware, ImportBeanDefinitionRegistrar {

    private BeanFactory beanFactory;
    private Environment environment;

    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
      // 如果没有配置主动扫描的包门路,那么则终止扫描 Mapper
      if (!AutoConfigurationPackages.has(this.beanFactory)) {logger.debug("Could not determine auto-configuration package, automatic mapper scanning disabled.");
        return;
      }

      logger.debug("Searching for mappers annotated with @Mapper");
      // 获取主动扫描的门路
      List<String> packages = AutoConfigurationPackages.get(this.beanFactory);
      if (logger.isDebugEnabled()) {packages.forEach(pkg -> logger.debug("Using auto-configuration base package'{}'", pkg));
      }
      // 创立一个 MapperScannerConfigurer 的 BeanDefinitionBuilder
      // 并且设置 MapperScannerConfigurer 的字段,如 processPropertyPlaceHolders、annotationClass、basePackage 等字段
      // 后续 MapperScannerConfigurer 就会通过这些字段信息去扫描包
      BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(MapperScannerConfigurer.class);
      builder.addPropertyValue("processPropertyPlaceHolders", true);
      // annotationClass 示意扫描的包中必须要有指定的注解,这里指定要有 Mapper 这个注解
      builder.addPropertyValue("annotationClass", Mapper.class);
      builder.addPropertyValue("basePackage", StringUtils.collectionToCommaDelimitedString(packages));
      BeanWrapper beanWrapper = new BeanWrapperImpl(MapperScannerConfigurer.class);
      Set<String> propertyNames = Stream.of(beanWrapper.getPropertyDescriptors()).map(PropertyDescriptor::getName)
          .collect(Collectors.toSet());
      if (propertyNames.contains("lazyInitialization")) {
        // Need to mybatis-spring 2.0.2+
        builder.addPropertyValue("lazyInitialization", "${mybatis.lazy-initialization:false}");
      }
      if (propertyNames.contains("defaultScope")) {
        // Need to mybatis-spring 2.0.6+
        builder.addPropertyValue("defaultScope", "${mybatis.mapper-default-scope:}");
      }

      // 默认设置 sqlSessionTemplateBeanName 的值为 sqlSessionTemplate  
      boolean injectSqlSession = environment.getProperty("mybatis.inject-sql-session-on-mapper-scan", Boolean.class,
          Boolean.TRUE);
      if (injectSqlSession && this.beanFactory instanceof ListableBeanFactory) {ListableBeanFactory listableBeanFactory = (ListableBeanFactory) this.beanFactory;
        Optional<String> sqlSessionTemplateBeanName = Optional
            .ofNullable(getBeanNameForType(SqlSessionTemplate.class, listableBeanFactory));
        Optional<String> sqlSessionFactoryBeanName = Optional
            .ofNullable(getBeanNameForType(SqlSessionFactory.class, listableBeanFactory));
        if (sqlSessionTemplateBeanName.isPresent() || !sqlSessionFactoryBeanName.isPresent()) {
          builder.addPropertyValue("sqlSessionTemplateBeanName",
              sqlSessionTemplateBeanName.orElse("sqlSessionTemplate"));
        } else {builder.addPropertyValue("sqlSessionFactoryBeanName", sqlSessionFactoryBeanName.get());
        }
      }
      builder.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);

      // 注册 MapperScannerConfigurer 的 BeanDefinition
      registry.registerBeanDefinition(MapperScannerConfigurer.class.getName(), builder.getBeanDefinition());
    }

    // 疏忽前面的代码
  }

  /**
  * 该类应用了 @Configuration 注解,故在调用 AutoConfiguredMapperScannerRegistrar#registerBeanDefinitions() 前,先通过这个类的逻辑:* 如果是曾经存在了 MapperFactoryBean 或者是 MapperScannerConfigurer 的 Bean
  * 那么就不会加载 AutoConfiguredMapperScannerRegistrar 的 Bean 了,因而也不会去创立 MapperScannerConfigurer 的 BeanDefinition,做后续的 Mapper 扫描了。* 其中 MapperScannerConfigurer 的 Bean 能够通过应用 @MapperScan 注解来创立(故如果应用了 @MapperScan 注解,就不会主动扫描 @Mapper 注解的 Mapper)* 或者咱们自定义了一个 Bean,返回的是 MapperFactoryBean,那么也不会主动扫描 @Mapper 注解的 Mapper
  */
  @org.springframework.context.annotation.Configuration(proxyBeanMethods = false)
  @Import(AutoConfiguredMapperScannerRegistrar.class)
  @ConditionalOnMissingBean({MapperFactoryBean.class, MapperScannerConfigurer.class})
  public static class MapperScannerRegistrarNotFoundConfiguration implements InitializingBean {

    @Override
    public void afterPropertiesSet() {
      logger.debug("Not found configuration for registering mapper bean using @MapperScan, MapperFactoryBean and MapperScannerConfigurer.");
    }

  }
}

@MapperScan 注解

@MapperScan 注解是 mybatis 主动扫描的罕用形式。
它通过应用了 @Import 注解,导入了 MapperScannerRegistrar 类,并且后续通过 MapperScannerRegistrar 来做 Mapper 扫描的逻辑。
MapperScan 的源码如下:

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@Import(MapperScannerRegistrar.class)
@Repeatable(MapperScans.class)
public @interface MapperScan {// 疏忽 MapperScan 注解的成员信息}

MapperScannerRegistrar

MapperScannerRegistrar 与扫描 @Mapper 注解的 AutoConfiguredMapperScannerRegistrar 一样,也是继承了 ImportBeanDefinitionRegistrar 接口,重写了 registerBeanDefinitions 办法。
另外 MapperScannerRegistrar 外部保护了 RepeatingRegistrar 动态类,该类继承了 MapperScannerRegistrar,性能与 MapperScannerRegistrar 统一,然而给 @MapperScans 注解应用。
故这里只探讨 MapperScannerRegistrar 的源码。

源码剖析

public class MapperScannerRegistrar implements ImportBeanDefinitionRegistrar, ResourceLoaderAware {

    /**
    * 实现了 ImportBeanDefinitionRegistrar 的 registerBeanDefinitions() 办法
    */
    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {// 通过 AnnotationAttributes.fromMap() 办法,获取 @MapperScan 注解的成员变量的值
        // 如果没有应用到 @MapperScan 注解,那么 AnnotationAttributes.fromMap() 办法就会返回 null
        // 说白了就是判断有没有用到 @MapperScan 注解,如果没有用到,就不会主动扫描 Mapper
        AnnotationAttributes mapperScanAttrs = AnnotationAttributes
            .fromMap(importingClassMetadata.getAnnotationAttributes(MapperScan.class.getName()));
        if (mapperScanAttrs != null) {
            // 调用上面的办法,去创立 MapperScannerConfigurer 的 BeanDefinition 
            registerBeanDefinitions(importingClassMetadata, mapperScanAttrs, registry,
                generateBaseBeanName(importingClassMetadata, 0));
        }
    }

    /**
    * 创立并注册 MapperScannerConfigurer 的 BeanDefinition
    * 在创立过程中把 @MapperScan 注解的成员变量
    * 都增加到 MapperScannerConfigurer 的 BeanDefinition 的 PropertyValues 上
    */
    void registerBeanDefinitions(AnnotationMetadata annoMeta, AnnotationAttributes annoAttrs,BeanDefinitionRegistry registry, String beanName) {
        // 先创立 MapperScannerConfigurer 的 BeanDefinition 
        BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(MapperScannerConfigurer.class);
        // 把 MapperScan 注解的成员变量,都增加到 BeanDefinition 的 PropertyValues 上
        builder.addPropertyValue("processPropertyPlaceHolders", true);

        Class<? extends Annotation> annotationClass = annoAttrs.getClass("annotationClass");
        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("basePackages")).filter(StringUtils::hasText)
            .collect(Collectors.toList()));

        basePackages.addAll(Arrays.stream(annoAttrs.getClassArray("basePackageClasses")).map(ClassUtils::getPackageName)
            .collect(Collectors.toList()));

        if (basePackages.isEmpty()) {basePackages.add(getDefaultBasePackage(annoMeta));
        }

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

        String defaultScope = annoAttrs.getString("defaultScope");
        if (!AbstractBeanDefinition.SCOPE_DEFAULT.equals(defaultScope)) {builder.addPropertyValue("defaultScope", defaultScope);
        }

        builder.addPropertyValue("basePackage", StringUtils.collectionToCommaDelimitedString(basePackages));

        // for spring-native
        builder.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
        // 最初注册 BeanDefinition 到 BeanDefinitionRegistry,给后续 Bean 的创立应用
        registry.registerBeanDefinition(beanName, builder.getBeanDefinition());
    }

    private static String generateBaseBeanName(AnnotationMetadata importingClassMetadata, int index) {return importingClassMetadata.getClassName() + "#" + MapperScannerRegistrar.class.getSimpleName() + "#" + index;}

    private static String getDefaultBasePackage(AnnotationMetadata importingClassMetadata) {return ClassUtils.getPackageName(importingClassMetadata.getClassName());
    }
}

MapperScannerConfigurer

MapperScannerConfigurer 是 Mapper 主动注入的外围,它实现了以下这些接口:

  • BeanDefinitionRegistryPostProcessor
  • InitializingBean
  • ApplicationContextAware
  • BeanNameAware

其中,主动注入 Mapper 的逻辑,次要是实现了 BeanDefinitionRegistryPostProcessor#registerBeanDefinitions() 办法。

源码如下:

// MapperScannerConfigurer 的一些成员变量,用于给扫描 Mapper 在生成 BeanDefinition 时应用
private String basePackage;
private boolean addToConfig = true;
private String lazyInitialization;
private SqlSessionFactory sqlSessionFactory;
private SqlSessionTemplate sqlSessionTemplate;
private String sqlSessionFactoryBeanName;
private String sqlSessionTemplateBeanName;
private Class<? extends Annotation> annotationClass;
private Class<?> markerInterface;
private Class<? extends MapperFactoryBean> mapperFactoryBeanClass;
private ApplicationContext applicationContext;
private String beanName;
private boolean processPropertyPlaceHolders;
private BeanNameGenerator nameGenerator;
private String defaultScope;

/**
* 先去创立 ClassPathMapperScanner , 而后调用 ClassPathMapperScanner#scan() 办法去扫描 Mapper 
*/
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {if (this.processPropertyPlaceHolders) {processPropertyPlaceHolders();
    }

    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));
    }
    if (StringUtils.hasText(defaultScope)) {scanner.setDefaultScope(defaultScope);
    }
    scanner.registerFilters();
    scanner.scan(StringUtils.tokenizeToStringArray(this.basePackage, ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS));
}

从下面的源码中看,实际上是去创立 ClassPathMapperScanner 的类,而后调用 scan() 办法来创立 Mapper。

ClassPathMapperScanner#scan()

ClassPathMapperScannerClassPathBeanDefinitionScanner 的子类,而下面提到的 scan() 办法理论是 ClassPathBeanDefinitionScanner 的。
该办法次要是扫描指定包门路下的 Mapper,而后转换成 BeanDefinition,这些 BeanDefintion 携带的 beanClass 信息是 MapperFactoryBean。
并在后续的 Spring Bean 创立流程中,把这些 BeanDefinition 转换成对应的 Bean(本文不探讨 Spring Bean 初始化流程)。

源码如下:

/**
* ClassPathBeanDefinitionScanner#scan() 办法
*/
public int scan(String... basePackages) {int beanCountAtScanStart = this.registry.getBeanDefinitionCount();

    // 因为 ClassPathMapperScanner 重写了 doScan() 办法
    // 故这里实际上是调用 ClassPathMapperScanner#doScan() 办法
    doScan(basePackages);

    // Register annotation config processors, if necessary.
    if (this.includeAnnotationConfig) {AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
    }

    return (this.registry.getBeanDefinitionCount() - beanCountAtScanStart);
}

/**
* ClassPathMapperScanner#doScan() 办法
*/
public Set<BeanDefinitionHolder> doScan(String... basePackages) {// 调用 ClassPathBeanDefinitionScanner#doScan() 办法 , 扫描 Mapper
    Set<BeanDefinitionHolder> beanDefinitions = super.doScan(basePackages);

    if (beanDefinitions.isEmpty()) {if (printWarnLogIfNotFoundMappers) {LOGGER.warn(() -> "No MyBatis mapper was found in'" + Arrays.toString(basePackages)
            + "'package. Please check your configuration.");
        }
    } else {
        // 把扫描失去的 BeanDefinitionHolder 列表元素中的 BeanDefinition 的 beanClass 属性设置成 MapperFactoryBean 类型 
        processBeanDefinitions(beanDefinitions);
    }

    return beanDefinitions;
}

/**
* ClassPathBeanDefinitionScanner#doScan() 办法
* 这里实际上是扫描指定包门路下的 Mapper,并将它们封装成 BeanDefinitionHolder 列表返回 
*/
protected Set<BeanDefinitionHolder> doScan(String... basePackages) {Assert.notEmpty(basePackages, "At least one base package must be specified");
    Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<>();
    for (String basePackage : basePackages) {
        // 从指定包目录下扫描 Mapper
        Set<BeanDefinition> candidates = findCandidateComponents(basePackage);
        for (BeanDefinition candidate : candidates) {ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);
            candidate.setScope(scopeMetadata.getScopeName());
            String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);
            // 对 BeanDeifintion 设置默认值
            if (candidate instanceof AbstractBeanDefinition) {postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName);
            }
            if (candidate instanceof AnnotatedBeanDefinition) {AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);
            }
            // 判断这个 BeanDefinition 是否存在,失常来说是不存在的,如果存在的话,那就证实这个 Mapper 的名字重名或者其余起因。// 如果 BeanDefinition 不存在,则增加这个 BeanDefinition 到 BeanDefinitionRegistry 中去
            // 并增加到要返回的 BeanDefinition 列表上,给后续转换 MapperFactoryBean 应用 
            if (checkCandidate(beanName, candidate)) {BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
                definitionHolder =
                        AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
                beanDefinitions.add(definitionHolder);
                registerBeanDefinition(definitionHolder, this.registry);
            }
        }
    }
    return beanDefinitions;
}

/**
* ClassPathMapperScanner#processBeanDefinitions()
* 该办法就是将扫描到的 Mapper 的 BeanDefinitionHolder 的信息进行批改
* 其中蕴含了将 BeanDefinitionHolder 的 BeanDefinition 的 beanClass 信息批改成 MapperFactoryBean 的逻辑
* 因而前面通过 BeanDefinition 所创立进去的 Bean,实际上是 MapperFactoryBean 类型
*/
private void processBeanDefinitions(Set<BeanDefinitionHolder> beanDefinitions) {
    AbstractBeanDefinition definition;
    BeanDefinitionRegistry registry = getRegistry();
    for (BeanDefinitionHolder holder : beanDefinitions) {definition = (AbstractBeanDefinition) holder.getBeanDefinition();
        boolean scopedProxy = false;
        // 如果这个 BeanDefinition 是一个代理类,那么就去拿它代理的 BeanDefinition
        if (ScopedProxyFactoryBean.class.getName().equals(definition.getBeanClassName())) {definition = (AbstractBeanDefinition) Optional
                .ofNullable(((RootBeanDefinition) definition).getDecoratedDefinition())
                .map(BeanDefinitionHolder::getBeanDefinition).orElseThrow(() -> new IllegalStateException("The target bean definition of scoped proxy bean not found. Root bean definition[" + holder + "]"));
            scopedProxy = true;
        }
        String beanClassName = definition.getBeanClassName();
        LOGGER.debug(() -> "Creating MapperFactoryBean with name'" + holder.getBeanName() + "'and'" + beanClassName
            + "'mapperInterface");

        // 将 Mapper 全限定类名增加到构造方法的参数进去
        definition.getConstructorArgumentValues().addGenericArgumentValue(beanClassName); // issue #59
        try {
            // 尝试将 Mapper 全限定类名增加到 BeanDefinition 的 PropertyValues 的 map 中去。definition.getPropertyValues().add("mapperInterface", Resources.classForName(beanClassName));
        } catch (ClassNotFoundException ignore) {// ignore}
        // 批改 BeanClass 的信息,把 Mapper 的 class 替换成 MapperFactoryBean
        definition.setBeanClass(this.mapperFactoryBeanClass);

        // 上面的代码,都是将 ClassPathMapperScanner 的成员变量的信息,都增加到 BeanDifinition 的 PropertyValues 中去。definition.getPropertyValues().add("addToConfig", this.addToConfig);

        // Attribute for MockitoPostProcessor
        // https://github.com/mybatis/spring-boot-starter/issues/475
        definition.setAttribute(FACTORY_BEAN_OBJECT_TYPE, beanClassName);

        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;
        }

        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;
        }

        if (!explicitFactoryUsed) {LOGGER.debug(() -> "Enabling autowire by type for MapperFactoryBean with name'" + holder.getBeanName() + "'.");
            definition.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_BY_TYPE);
        }

        definition.setLazyInit(lazyInitialization);

        if (scopedProxy) {continue;}

        if (ConfigurableBeanFactory.SCOPE_SINGLETON.equals(definition.getScope()) && defaultScope != null) {definition.setScope(defaultScope);
        }

        // 对非单例类型的 Mapper 做的逻辑
        if (!definition.isSingleton()) {BeanDefinitionHolder proxyHolder = ScopedProxyUtils.createScopedProxy(holder, registry, true);
            if (registry.containsBeanDefinition(proxyHolder.getBeanName())) {registry.removeBeanDefinition(proxyHolder.getBeanName());
            }
            registry.registerBeanDefinition(proxyHolder.getBeanName(), proxyHolder.getBeanDefinition());
        }

    }
}

MapperFactoryBean

MapperFactoryBean 是 Mybatis/Spring 用来示意 Mapper 的 Bean,它继承了 SqlSessionDaoSupport,实现了 FactoryBean 接口。
所以在获取 MapperFactoryBean 的 Bean 时,实际上是调用了 MapperFactoryBean#getObject() 办法,返回 MapperProxy 的代理类。
对于 MapperFactoryBean,后续再独自探讨。

正文完
 0