现象
旧项目启动时出现以下报错,但被及时捕获了所以不影响启动,但想干掉它:
结论
当项目启动后,会执行部分类的初始化方法【1】,以 loadCache 方法为例(项目启动时通过依赖注入,找到实现了某个 interface 的所有 class【2】,遍历执行这些 class 的 loadCache 方法)。
因为该 interface 位于 MyBatis 的依赖扫描路径内【3】,所以在【2】中找出的 class 里包含了MybatisMapperProxy。MybatisMapperProxy 没有实现该 interface 的 loadCache 方法,所以出现了异常:org.apache.ibatis.binding.BindingException: Invalid bound statement (not found)
【1】通过 ApplicationRunner 在 SpringBoot 项目启动后帮助完成项目的初始化,感兴趣可以搜一下 CommandLineRunner、ApplicationRunner 和 PostConstruct 这三者的区别
【2】通过依赖注入,找到实现了某个 interface 的所有 class(顺带提一嘴,这里的依赖注入可以通过构造方法进行注入,那才是 Spring 官方推荐的方式)
【3】由于该 interface 位于 MyBatis 的依赖扫描路径内,而 Mybatis 通过 MapperProxy 类实现了 InvocationHandler 接口,利用了 JDK 的动态代理机制,在运行时为该 interface 生成代理对象,这就导致了 MybatisMapperProxy 实际是该 interface 的代理实例,所以在进行依赖注入时 MybatisMapperProxy 会被一并找出。
解决方案
1、在 MyBatis 的 MapperScan 中排除该 interface,但是因为旧项目里的 Mybatis 源码里没有排除选项(版本较老),所以该项解决方案对我不适用
2、写一个该 interface 的 loadCache 方法的默认实现