@autoWired Injected objects that do not match expectations. The result was a problem with the Mybatis scan

@Mapper

This annotation is the default annotation class scanned when Mybatis is automatically configured

MybatisAutoConfiguration.AutoConfiguredMapperScannerRegistrar#registerBeanDefinitions

public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {

      logger.debug("Searching for mappers annotated with @Mapper");

      ClassPathMapperScanner scanner = new ClassPathMapperScanner(registry);

      try {
        if(this.resourceLoader ! = null) { scanner.setResourceLoader(this.resourceLoader); } List<String> packages = AutoConfigurationPackages.get(this.beanFactory);if (logger.isDebugEnabled()) {
          for (String pkg : packages) {
            logger.debug("Using auto-configuration base package '{}'", pkg); }} / / scan @ Mapper annotate the scanner setAnnotationClass (Mapper. Class); scanner.registerFilters(); scanner.doScan(StringUtils.toStringArray(packages)); } catch (IllegalStateException ex) { logger.debug("Could not determine auto-configuration package, automatic mapper scanning disabled.", ex); }}Copy the code

@MapperScan

Set scan properties for manual scanning. You can set scan packages, scan notes and other information

MapperScannerRegistrar#registerBeanDefinitions

public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {

    AnnotationAttributes annoAttrs = AnnotationAttributes.fromMap(importingClassMetadata.getAnnotationAttributes(MapperScan.class.getName()));
    ClassPathMapperScanner scanner = new ClassPathMapperScanner(registry);

    // this check is needed in Spring 3.1
    if(resourceLoader ! = null) { scanner.setResourceLoader(resourceLoader); } Class<? extends Annotation> annotationClass = annoAttrs.getClass("annotationClass");
    if(! Annotation.class.equals(annotationClass)) { scanner.setAnnotationClass(annotationClass); } Class<? > markerInterface = annoAttrs.getClass("markerInterface");
    if(! Class.class.equals(markerInterface)) { scanner.setMarkerInterface(markerInterface); } Class<? extends BeanNameGenerator> generatorClass = annoAttrs.getClass("nameGenerator");
    if(! BeanNameGenerator.class.equals(generatorClass)) { scanner.setBeanNameGenerator(BeanUtils.instantiateClass(generatorClass)); } Class<? extends MapperFactoryBean> mapperFactoryBeanClass = annoAttrs.getClass("factoryBean");
    if(! MapperFactoryBean.class.equals(mapperFactoryBeanClass)) { scanner.setMapperFactoryBean(BeanUtils.instantiateClass(mapperFactoryBeanClass)); } scanner.setSqlSessionTemplateBeanName(annoAttrs.getString("sqlSessionTemplateRef"));
    scanner.setSqlSessionFactoryBeanName(annoAttrs.getString("sqlSessionFactoryRef"));

    List<String> basePackages = new ArrayList<String>();
    for (String pkg : annoAttrs.getStringArray("value")) {
      if(StringUtils.hasText(pkg)) { basePackages.add(pkg); }}for (String pkg : annoAttrs.getStringArray("basePackages")) {
      if(StringUtils.hasText(pkg)) { basePackages.add(pkg); }}for(Class<? > clazz : annoAttrs.getClassArray("basePackageClasses")) {
      basePackages.add(ClassUtils.getPackageName(clazz));
    }
    scanner.registerFilters();
    scanner.doScan(StringUtils.toStringArray(basePackages));
  }
Copy the code

As you can see from the code above, everything that is scanned by @mapperscan is scanned (injected into MapperFactoryBean).

The problem

If @Mapperscan scans all by default, and @SpringBoot scans all, is the object in this MapperFactoryBean or a real object?

One for @Service and one for MybatisScan for injected MapperFactoryBean

To solve

Again, it’s not about design, it’s about use

Why does Mybatis inject all classes according to the path in the scan package

If let you design, how do you know that the class scanned is not the class MyBatis needs to inject?

  1. Special said

    This method is already supported by @mapper, and does not need to scan, the default load, if you use @mapperscan, it is really redundant

  2. Only Mapper packets are scanned

    The problem is, if you’re just using it, if you don’t think about it, you’re probably just going to scan a big bag. There will be problems

Personal advice

In fact, personal advice can be automatic try not to manual. Because the supplier has prepared very well for the automatic, there will be no problem, but just the manual part will have some artificial omission or thoughtless or unable to achieve problems, resulting in the user does not know the end of the

So I think the best way is @Mapper, automatic