目录
报错信息
可能原因
结论
报错信息
最近在学Spring Boot,今天在做Spring Boot + mybatis Plus + Vue项目时启动后端报错:
java">org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'loginController': Unsatisfied dependency expressed through field 'a***ountMapper';
nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'a***ountMapper' defined in file
[D:\ecas\workspace\ecas\target\classes\***\example\ecas\persistence\A***ountMapper.class]: Unsatisfied dependency expressed through bean property 'sqlSessionFactory'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'sqlSessionFactory' defined in class path resource
[***/baomidou/mybatisplus/autoconfigure/MybatisPlusAutoConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate
[org.apache.ibatis.session.SqlSessionFactory]: Factory method 'sqlSessionFactory' threw exception; nested exception is java.lang.NoClassDefFoundError: org/mybatis/logging/LoggerFactory
先看报错信息,说出现了一个依赖注入异常(UnsatisfiedDependencyException),在创建名为 'loginController' 的bean时出错,并且问题出现在字段 'a***ountMapper' 上。
我的loginController里面调用了A***ountMapper和EmailService接口,并且都标了@Autowired自动注入字段,之前报过错拿不到emailService,所以写了一个setEmailService方法注入了:
// loginController
package ***.example.ecas.controller;
import ***.example.ecas.persistence.A***ountMapper;
import ***.example.ecas.service.SmsService;
import ***.example.ecas.pojo.A***ount;
import ***.example.ecas.service.EmailService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
@RestController
@Controller
public class LoginController {
@Autowired
A***ountMapper a***ountMapper;
@Autowired
private EmailService emailService;
@Autowired
public void setEmailService(EmailService emailService) {
this.emailService = emailService;
}
// 后面是一些方法,没什么问题
}
然后是嵌套异常显示在创建名为 'a***ountMapper' 的bean时也遇到了依赖注入异常。 接着,嵌套异常表明在 'sqlSessionFactory' 属性上设置bean时出现了问题,这与类路径中的MybatisPlusAutoConfiguration 类有关。
最后,嵌套异常显示在调用工厂方法 'sqlSessionFactory' 时出现了异常,具体报错为 java.lang.NoClassDefFoundError: org/mybatis/logging/LoggerFactory。
大概明白了,扫不到A***ountMapper => 创建bean a***ountMapper出错 => loginController出错 / 方法sqlSessionFactory出错。
可能原因
同时在网上查了半天,总结一下这个问题可能的原因有:
- 相关依赖导入问题。检查项目的依赖配置文件(如 Maven 的 pom.xml 或 Gradle 的 build.gradle)以确保正确引入了所需的 Spring、MyBatis 和 MyBatis Plus 相关依赖;
- 依赖版本的兼容性问题,不过这个IDE应该会标红,总之注意一下;
- 代码配置问题。确保 MyBatis 和 MyBatis Plus 的相关配置(如数据库连接信息、Mapper 扫描等)正确无误。Controller类上面记得加@Controller注解,调用的service类要加@Service注解,Mapper层类上要添加@Mapper注解,启动类上包要扫描到loginController类;
- 路径或者格式不正确问题。检查项目的类路径中包含所需的类和资源文件。检查配置文件、Mapper接口以及 MyBatis 和 MyBatis Plus 的其他必要组件是否正确放置在项目的编译输出目录(例如 target/classes)中;
- 缓存或构建问题。解决办法就是重新构建/清理项目。
我一开始检查了我的注解,都写得好好的(后面发现有冗余,比如我的loginController上面注解了@RestController又标了@Controller,然后A***ountMapper上面标了@Mapper又@***ponent,这种情况都只用取前者,不然容易报错,不过这不是上面错误的主要原因)
直到我看到第3点,嗯?启动类上的包扫描?什么玩意我没有啊:
// EcasApplication
package ***.example.ecas;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class EcasApplication {
public static void main(String[] args) {
SpringApplication.run(EcasApplication.class, args);
}
}
那就加点注解试试看呗,虽然我不会写,但是我可以抄别人的啊!
于是也没细想,自作聪明东拼西凑在Application上面加了一堆注解,如下:
package ***.example.ecas;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.data.jpa.JpaRepositoriesAutoConfiguration;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.context.annotation.***ponentScan;
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class, JpaRepositoriesAutoConfiguration.class})
@***ponentScan("***.example.ecas.persistence")
public class EcasApplication {
public static void main(String[] args) {
SpringApplication.run(EcasApplication.class, args);
}
}
不记得在哪抄了一个@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class, JpaRepositoriesAutoConfiguration.class})
发现不错,报错消息的格式都变好看了,我应该是对的吧:
***************************
APPLICATION FAILED TO START
***************************
Description:
Field a***ountMapper in ***.example.ecas.controller.LoginController required a bean of type '***.example.ecas.persistence.A***ountMapper' that could not be found.
The injection point has the following annotations:
- @org.springframework.beans.factory.annotation.Autowired(required=true)
Action:
Consider defining a bean of type '***.example.ecas.persistence.A***ountMapper' in your configuration.
后来才知道
@SpringBootApplication注解用于标示主应用程序类;
exclude参数用于指定不需要自动配置的类;
这里排除的是
DataSourceAutoConfiguration.class
和JpaRepositoriesAutoConfiguration.class,
这意味着在应用程序启动过程中,Spring Boot将不会自动配置数据源和JPA存储库相关的bean。
继续看报错信息,既然他说是扫描不到persistence目录下的A***ountMapper,识别不了bean导致的,那就加个@***ponentScan("***.example.ecas.persistence")
ok能够正常运行了,测试一下......发现能启动,但是所有的接口都报404错误,后台日志没有任何反应。
看了一下后台日志信息,发现和平时的不一样,平时是这样的
这次mybatis plus的图标没有出来,猜想应该和mybatis-plus有关;loginController里所有接口都报404,推测是没有识别controller。
于是检查了pom.xml,发现既导入了mybatis-plus又导入了mybatis的依赖,所以出现嵌套异常。
把mybatis的依赖注释掉;
检查启动类注解,发现和上面乱写注释一样,
EcasApplication应该用@MapperScan("***.example.ecas.persistence")注释
而不是@***ponentScan("***.example.ecas.persistence")注释
A***ountMapper是Mapper类就不要用***ponent注释!!
之前加的@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class, JpaRepositoriesAutoConfiguration.class})也要把括号删掉!!
package ***.example.ecas;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
@MapperScan("***.example.ecas.persistence")
public class EcasApplication {
public static void main(String[] args) {
SpringApplication.run(EcasApplication.class, args);
}
}
再启动,一切ok。
结论
- 检查注释,不要冗余,什么类该用什么注释搞清楚;
- pom.xml里的依赖mybatis-plus和mybatis不能重复导入!