好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

解决Spring使用@MapperScan问题

问题场景

今天小编在MyBatis 整合Spring 的时候,使用到了@MapperScan,在启动期出现了一个错误:

Invalid default: public abstract java.lang.Class org.mybatis.spring.annotation.MapperScan.factoryBean()

对于这个错误,小编也是倍感无奈,怎么会出现这个错误呢,看一下我的依赖有没有错误:

?

1

2

3

4

5

6

7

8

9

10

     compile(project( ":spring-context" ))

//    compile(project(":spring-instrument"))

     // https://mvnrepository测试数据/artifact/cglib/cglib

     compile group: 'cglib' , name: 'cglib' , version: '2.2.2'

     // https://mvnrepository测试数据/artifact/mysql/mysql-connector-java

     compile group: 'mysql' , name: 'mysql-connector-java' , version: '8.0.21'

     // https://mvnrepository测试数据/artifact/org.mybatis/mybatis

     compile group: 'org.mybatis' , name: 'mybatis' , version: '3.5.2'

     // https://mvnrepository测试数据/artifact/org.mybatis/mybatis-spring

     compile group: 'org.mybatis' , name: 'mybatis-spring' , version: '2.0.2'

完全没得毛病呀,他妈的,究竟是哪里出现了问题呢,小编这时将SpringFramework 源码从github 上clone 下来了,导入idea 开始寻找问题所在。。。

问题根源

经过不懈的努力,小编终于找到了问题根源,在AnnotationsScanner 类中的这个方法:

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

static Annotation[] getDeclaredAnnotations(AnnotatedElement source, boolean defensive) {

   boolean cached = false ;

   Annotation[] annotations = declaredAnnotationCache.get(source);

   if (annotations != null ) {

    cached = true ;

   }

   else {

    // 使用@MapperScan 的时候会报错,引入spring-jdbc 即可

    // 具体原因暂时还不清楚

    // Invalid default: public abstract java.lang.Class org.mybatis.spring.annotation.MapperScan.factoryBean()

    annotations = source.getDeclaredAnnotations();

    if (annotations.length != 0 ) {

     boolean allIgnored = true ;

     for ( int i = 0 ; i < annotations.length; i++) {

      Annotation annotation = annotations[i];

      if (isIgnorable(annotation.annotationType()) ||

        !AttributeMethods.forAnnotationType(annotation.annotationType()).isValid(annotation)) {

       annotations[i] = null ;

      }

      else {

       allIgnored = false ;

      }

     }

     annotations = (allIgnored ? NO_ANNOTATIONS : annotations);

     if (source instanceof Class || source instanceof Member) {

      declaredAnnotationCache.put(source, annotations);

      cached = true ;

     }

    }

   }

   if (!defensive || annotations.length == 0 || !cached) {

    return annotations;

   }

   return annotations.clone();

  }

AnnotatedElement 对于这个类,小编也是不太清楚,这时也倍感无奈,这个方法主要做的事情就是将Appconfig 配置类中的注解扫描下来,那会不会是注解的问题呢,在@MapperScan 注解的注释中发现小编的代码与MyBatis-Spring 开发团队提供的实例代码一致,这就让人想不明白了:

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

* <pre class = "code" >

* &# 064 ;Configuration

* &# 064 ;MapperScan( "org.mybatis.spring.sample.mapper" )

* public class AppConfig {

*

*   &# 064 ;Bean

*   public DataSource dataSource() {

*     return new EmbeddedDatabaseBuilder().addScript( "schema.sql" ).build();

*   }

*

*   &# 064 ;Bean

*   public DataSourceTransactionManager transactionManager() {

*     return new DataSourceTransactionManager(dataSource());

*   }

*

*   &# 064 ;Bean

*   public SqlSessionFactory sqlSessionFactory() throws Exception {

*     SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();

*     sessionFactory.setDataSource(dataSource());

*     return sessionFactory.getObject();

*   }

* }

* </pre>

问题追溯

我这个时候被起疯了都,从GitHub 上由把mybatis-spring 的源码clone 了下来,导入idea,首先看一下mybatis-spring 的依赖:

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

< dependencies >

    <!-- Compile dependencies -->

    < dependency >

      < groupId >org.mybatis</ groupId >

      < artifactId >mybatis</ artifactId >

      < version >${mybatis.version}</ version >

      < scope >provided</ scope >

    </ dependency >

    < dependency >

      < groupId >org.springframework</ groupId >

      < artifactId >spring-context</ artifactId >

      < version >${spring.version}</ version >

      < scope >provided</ scope >

    </ dependency >

    < dependency >

      < groupId >org.springframework</ groupId >

      < artifactId >spring-jdbc</ artifactId >

      < version >${spring.version}</ version >

      < scope >provided</ scope >

    </ dependency >

    < dependency >

      < groupId >org.springframework.batch</ groupId >

      < artifactId >spring-batch-infrastructure</ artifactId >

      < version >${spring-batch.version}</ version >

      < scope >provided</ scope >

    </ dependency >

从依赖中看到了什么,tmd,<scope>provided</scope>,这个怎么讲,太无语了,其中它引入了spring-jdbc 的依赖。想象一下,@MapperScan 注解中是不是也使用到了spring-jdbc 的类,然后在使用@MapperScan 的时候没有加入spring-jdbc 的依赖,导致注解在扫描期间的错误,没毛病解释的通,找一下@MapperScan 中是否使用到了spring-jdbc 的依赖。

问题解决

果不其然,下面用一张图来看吧。

所以呢,在项目中加入spring-jdbc 完美解决。

SpringBoot  @MapperScan的注意事项

错误代码如下:

[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.mybatis.spring.MyBatisSystemException: nested exception is org.apache.ibatis.builder.BuilderException: Error invoking SqlProvider method (tk.mybatis.mapper.provider.base.BaseSelectProvider.dynamicSQL). Cause: java.lang.InstantiationException: tk.mybatis.mapper.provider.base.BaseSelectProvider] with root cause

检查@MapperScan导入的包是否为

?

1

import tk.mybatis.spring.annotation.MapperScan;

切记不要导成

?

1

import org.mybatis.spring.annotation.MapperScan

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

原文链接:https://blog.csdn.net/zhagnchong480/article/details/111562366

查看更多关于解决Spring使用@MapperScan问题的详细内容...

  阅读:24次