問題場景
今天小編在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.com/artifact/cglib/cglib compile group: 'cglib' , name: 'cglib' , version: '2.2.2' // https://mvnrepository.com/artifact/mysql/mysql-connector-java compile group: 'mysql' , name: 'mysql-connector-java' , version: '8.0.21' // https://mvnrepository.com/artifact/org.mybatis/mybatis compile group: 'org.mybatis' , name: 'mybatis' , version: '3.5.2' // https://mvnrepository.com/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