@MapperScan扫描包里混有@Service等问题如何解决

2022-07-16,,,,

@mapperscan扫描包混有@service

问题描述

@mapperscan注解配置的一般是dao或者mapper的扫描包,一般用于数据库操作,里面类的一般都是接口,如果在dao层有其他接口,比如说@service等就会报错

解决办法一

把service包移走,方法可行

解决办法二

不使用@mapperscan,在每个dao或者mapper里面加上注解@mapper,方法可行

解决办法三

使用自定义注解,在mybatis的注解比较完善的情况下,就不用自己搞多少

创建注解@mymapperscan

里面的属性全部抄袭@mapperscan

mapperscannerregistrar换成自己的

@retention(retentionpolicy.runtime)
@target(elementtype.type)
@documented
@import(mymapperscannerregistrar.class)
@repeatable(mapperscans.class)
public @interface mapperscan {
  string[] value() default {};
  string[] basepackages() default {};
 
  class<?>[] basepackageclasses() default {};
 
  class<? extends beannamegenerator> namegenerator() default beannamegenerator.class;
  class<? extends annotation> annotationclass() default annotation.class;
  class<?> markerinterface() default class.class;
 
  string sqlsessiontemplateref() default "";
  string sqlsessionfactoryref() default "";
  
  class<? extends mapperfactorybean> factorybean() default mapperfactorybean.class;
  string lazyinitialization() default "";
}

mymapperscannerregistrar扫描注册器

这个类和mybatis的一模一样,唯一的不同就是myclasspathmapperscanner是自己的扫描

public class mymapperscannerregistrar extends mapperscannerregistrar {
    private resourceloader resourceloader;
    /**
     * {@inheritdoc}
     */
    @override
    public void registerbeandefinitions(annotationmetadata importingclassmetadata, beandefinitionregistry registry) {
        annotationattributes annoattrs = annotationattributes.frommap(importingclassmetadata.getannotationattributes(mapperscan.class.getname()));
        //这个是自己的
        classpathmapperscanner scanner = new myclasspathmapperscanner(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));
    }
    /**
     * {@inheritdoc}
     */
    @override
    public void setresourceloader(resourceloader resourceloader) {
        this.resourceloader = resourceloader;
    }
}

myclasspathmapperscanner

自己的扫描类基本也是mybatis的,就是在判断上面改动了一点点

public class myclasspathmapperscanner extends classpathmapperscanner {
    public myclasspathmapperscanner(beandefinitionregistry registry) {
        super(registry);
    }
    @override
    protected boolean iscandidatecomponent(annotatedbeandefinition beandefinition) {
        boolean flag = super.iscandidatecomponent(beandefinition);
        //包名带有mapper的才会被mybatis代理
        boolean mapper = beandefinition.getbeanclassname().contains("mapper");
        return flag && mapper;
    }
}

现在只需要用自己的扫描注解即可,用法和mybatis的一模一样

解决办法四

这个是针对第三点的,作者使用第三点的时候mybatis版本为3.4.6

mybatis-spring版本为1.3.2,spring版本为5.x

当mybatis版本为3.5.2的mybatis-spring版本为2.0.2的时候

mapperscannerregistrar类扫描的方式发生了一点点变化,

还需要改写mapperscannerconfigurer类,其他的不变

完毕!

解决办法五

@mapperscan注解使用markerinterface或者annotationclass参数限制扫描的接口

@mapperscan包扫描的坑

在使用通用mapper执行查询时

由于不太注意顺手就导了spring的包:

import org.mybatis.spring.annotation.mapperscan;

结果就异常:

tk.mybatis.mapper.provider.base.baseselectprovider:xxxx

找了半天才发现是包的问题

应该导mybatis的mapperscan而不是spring中的包,正确的包名:

import tk.mybatis.spring.annotation.mapperscan;

以上为个人经验,希望能给大家一个参考,也希望大家多多支持。

《@MapperScan扫描包里混有@Service等问题如何解决.doc》

下载本文的Word格式文档,以方便收藏与打印。