(1)问题描述
自定义了一个 MyBatis 拦截器,用于拦截查询语句。拦截器的签名为:
@Component
@Intercepts(
@Signature(
type = Executor.class,
method = "query",
args = {MappedStatement.class, Object.class,
RowBounds.class, ResultHandler.class}
))
public class SelectSqlInterceptor implements Interceptor{…}
执行后抛出异常,完整异常日志如下:
java.lang.IllegalStateException: Failed to execute CommandLineRunner
at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:798) [spring-boot-2.3.3.RELEASE.jar:2.3.3.RELEASE]
at org.springframework.boot.SpringApplication.callRunners(SpringApplication.java:779) [spring-boot-2.3.3.RELEASE.jar:2.3.3.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:322) [spring-boot-2.3.3.RELEASE.jar:2.3.3.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1237) [spring-boot-2.3.3.RELEASE.jar:2.3.3.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1226) [spring-boot-2.3.3.RELEASE.jar:2.3.3.RELEASE]
at com.fsti.cc.core.ds.DSApplication.main(DSApplication.java:30) [classes/:na]
Caused by: org.apache.ibatis.exceptions.PersistenceException:
### Error opening session. Cause: org.apache.ibatis.plugin.PluginException: Could not find method on class org.apache.ibatis.javassist.bytecode.analysis.Executor named query. Cause: java.lang.NoSuchMethodException: org.apache.ibatis.javassist.bytecode.analysis.Executor.query(org.apache.ibatis.mapping.MappedStatement, java.lang.Object, org.apache.ibatis.session.RowBounds, org.apache.ibatis.session.ResultHandler)
### Cause: org.apache.ibatis.plugin.PluginException: Could not find method on class org.apache.ibatis.javassist.bytecode.analysis.Executor named query. Cause: java.lang.NoSuchMethodException: org.apache.ibatis.javassist.bytecode.analysis.Executor.query(org.apache.ibatis.mapping.MappedStatement, java.lang.Object, org.apache.ibatis.session.RowBounds, org.apache.ibatis.session.ResultHandler)
at org.apache.ibatis.exceptions.ExceptionFactory.wrapException(ExceptionFactory.java:30) ~[mybatis-3.5.6.jar:3.5.6]
at org.apache.ibatis.session.defaults.DefaultSqlSessionFactory.openSessionFromDataSource(DefaultSqlSessionFactory.java:100) ~[mybatis-3.5.6.jar:3.5.6]
at org.apache.ibatis.session.defaults.DefaultSqlSessionFactory.openSession(DefaultSqlSessionFactory.java:57) ~[mybatis-3.5.6.jar:3.5.6]
at org.mybatis.spring.SqlSessionUtils.getSqlSession(SqlSessionUtils.java:105) ~[mybatis-spring-2.0.6.jar:2.0.6]
at org.mybatis.spring.SqlSessionTemplate$SqlSessionInterceptor.invoke(SqlSessionTemplate.java:424) ~[mybatis-spring-2.0.6.jar:2.0.6]
at com.sun.proxy.$Proxy57.selectList(Unknown Source) ~[na:na]
at org.mybatis.spring.SqlSessionTemplate.selectList(SqlSessionTemplate.java:224) ~[mybatis-spring-2.0.6.jar:2.0.6]
at org.apache.ibatis.binding.MapperMethod.executeForMany(MapperMethod.java:147) ~[mybatis-3.5.6.jar:3.5.6]
at org.apache.ibatis.binding.MapperMethod.execute(MapperMethod.java:80) ~[mybatis-3.5.6.jar:3.5.6]
at org.apache.ibatis.binding.MapperProxy$PlainMethodInvoker.invoke(MapperProxy.java:152) ~[mybatis-3.5.6.jar:3.5.6]
at org.apache.ibatis.binding.MapperProxy.invoke(MapperProxy.java:85) ~[mybatis-3.5.6.jar:3.5.6]
at com.sun.proxy.$Proxy58.selectAll(Unknown Source) ~[na:na]
at com.fsti.cc.core.ds.DSApplication.run(DSApplication.java:35) [classes/:na]
at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:795) [spring-boot-2.3.3.RELEASE.jar:2.3.3.RELEASE]
... 5 common frames omitted
Caused by: org.apache.ibatis.plugin.PluginException: Could not find method on class org.apache.ibatis.javassist.bytecode.analysis.Executor named query. Cause: java.lang.NoSuchMethodException: org.apache.ibatis.javassist.bytecode.analysis.Executor.query(org.apache.ibatis.mapping.MappedStatement, java.lang.Object, org.apache.ibatis.session.RowBounds, org.apache.ibatis.session.ResultHandler)
at org.apache.ibatis.plugin.Plugin.getSignatureMap(Plugin.java:83) ~[mybatis-3.5.6.jar:3.5.6]
at org.apache.ibatis.plugin.Plugin.wrap(Plugin.java:44) ~[mybatis-3.5.6.jar:3.5.6]
at com.fsti.cc.core.ds.interceptor.SelectSqlInterceptor.plugin(SelectSqlInterceptor.java:55) ~[classes/:na]
at org.apache.ibatis.plugin.InterceptorChain.pluginAll(InterceptorChain.java:31) ~[mybatis-3.5.6.jar:3.5.6]
at org.apache.ibatis.session.Configuration.newExecutor(Configuration.java:681) ~[mybatis-3.5.6.jar:3.5.6]
at org.apache.ibatis.session.defaults.DefaultSqlSessionFactory.openSessionFromDataSource(DefaultSqlSessionFactory.java:96) ~[mybatis-3.5.6.jar:3.5.6]
... 17 common frames omitted
Caused by: java.lang.NoSuchMethodException: org.apache.ibatis.javassist.bytecode.analysis.Executor.query(org.apache.ibatis.mapping.MappedStatement, java.lang.Object, org.apache.ibatis.session.RowBounds, org.apache.ibatis.session.ResultHandler)
at java.lang.Class.getMethod(Class.java:1786) ~[na:1.8.0_181]
at org.apache.ibatis.plugin.Plugin.getSignatureMap(Plugin.java:80) ~[mybatis-3.5.6.jar:3.5.6]
... 22 common frames omitted
(2)原因分析
org.apache.ibatis.javassist.bytecode.analysis.Executor 类中并没有 query 方法,所以抛错。
(3)问题解决
实际上 MyBatis 依赖中包含两个同名的 Executor 类,自定义的拦截器签名需要的类是org.apache.ibatis.executor.Executor。我们进入该类源代码,可以看到确实有相应的 query 方法: