springboot多模块扫包中的@SpringBootApplication、@ComponentScan和@MapperScan问题
- 1. 前言
- 2. 处理swagger扫描多包问题
- 3. 启动类里获取spring容器
- 4. 处理上面问题的流程和解决对应的问题
- 4.1 移动 DogController 和 HelloWorldController 同包
- 4.1.1 问题1. required a bean of type
- 4.1.1.1 问题描述
- 4.1.1.2 问题原因
- 4.1.1.3 解决问题
- 4.1.2 问题2->@ComponentScan 与 @SpringBootApplication 问题
- 4.1.3 问题3->@MapperScan
- 4.1.3.1 启动类中 @MapperScan
- 4.1.3.2 配置文件中 @MapperScan
- 4.2 把 Dogcontroller 移回原包
- 5. 开发建议
1. 前言
- 在原有的项目里新增了一个module子模块
form-message
,但是在新增的子module里的controller里的接口在swagger在线文档里不展示,下面是解决此问题以及发现别问题的各种处理方法 - 问题如下:
2. 处理swagger扫描多包问题
- 这是首先要考虑的,需要在swagger配置文件里配置可扫描多包
关于配置可参考下面文章
关于前后端分离项目接口文档之Springboot整合knife4的使用.
3. 启动类里获取spring容器
- 再确保 swagger 配置没问题的情况下,可以试试下面的方法,下面代码添加到启动类里
- 代码如下:
@Bean
public CommandLineRunner appRun(ApplicationContext ac) {
return args -> {
/**
* 通过类名(BeanName)获取已注入对象
* 这里 helloWorld 是一个被注入到容器中的helloWorld==》helloWorldController类
*/
System.out.println("=====================================================");
Object helloWorld = ac.getBean("helloWorldController");
System.out.println(helloWorld);
System.out.println("=====================================================");
Object dog = ac.getBean("dogController");
System.out.println(dog);
};
}
- 启动看效果:
- 看到这里如果确定了不是swagger配置的问题,那么如果对spring容器以及注解很熟悉的,想必应该已经定位出问题了,下面的几乎可以不用看了,但是为了让大家更明白,所以我这里准备了下面的内容,一步一步来,让阅读的你更明白怎么回事,想继续的往下看吧!
4. 处理上面问题的流程和解决对应的问题
4.1 移动 DogController 和 HelloWorldController 同包
- 移动到同一个包下,这可能是部分同学为了方便起最爱做的,那我们不妨试试看
4.1.1 问题1. required a bean of type
4.1.1.1 问题描述
- 如下:
Description:
Field dogService in com.liu.susu.start.controller.DogController required a bean of type 'com.liu2.susu.message.service.DogService' 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 'com.liu2.susu.message.service.DogService' in your configuration.
- 看到这里,应该知道了,很显然这个类没有注入到Spring容器中去,检查实现类
- 很显然,实现类也没问题,@service注解也有,那问题出现在哪里呢?
4.1.1.2 问题原因
- 每一个Spring项目都有独立的Spring容器去存储自己项目中所注册的bean。
上面问题出现的原因就是:启动类StartApplication.java
启动时,模块form-start
中Spring容器加载时未能将模块form-message
中所定义的bean注册进Spring容器中,导致@Autowired
注入模块form-message
中的bean进行使用时,找不到对应的bean,才会出现上面的问题Consider defining a bean of type 'com.liu2.susu.message.service.DogService' in your configuration
.
4.1.1.3 解决问题
- 启动类启动时,让模块
form-start
的Spring容器启动时,去扫描模块form-message
包下的所有的组件并注册到模块form-start
的Spring容器中即可解决上述问题。解决问题如下继续……
4.1.2 问题2->@ComponentScan 与 @SpringBootApplication 问题
- 按照上面的分析,需要修改启动类上的注解了,
这个修改需要注意注解@ComponentScan
与 注解@SpringBootApplication
的使用
- 首先,springboot默认扫描启动类同级包和同级的子包内容
-
@ComponentScan
注解的作用是:扫描标注了@Controller、@Service、@Repository、@Component 的类 - 先给原启动类里的代码,如下:
- 如果在上面代码的基础上,直接使用 @SpringBootApplication 注解修改如下情况,是不可以的,问题并没有解决,如下:
@SpringBootApplication(scanBasePackages = {"com.liu.susu","com.liu2.susu"})
- 为什么还没有扫描到?
- 原因就是:
@ComponentScan 和@SpringBootApplication注解的包扫描有冲突,@ComponentScan注解包扫描会覆盖掉@SpringBootApplication的包扫描 - 要解决,需要把
@ComponentScan("com.liu.susu.*")
注释掉 或者@ComponentScan
扫描多包即可,如下两种写法都可以:
//@ComponentScan("com.liu.susu.*")
@ComponentScan(basePackages = {"com.liu.susu.*", "com.liu2.susu"})
@SpringBootApplication
//@SpringBootApplication(scanBasePackages = {"com.liu.susu","com.liu2.susu"})
//@ComponentScan("com.liu.susu.*")
//@ComponentScan(basePackages = {"com.liu.susu.*", "com.liu2.susu"})
//@SpringBootApplication
@SpringBootApplication(scanBasePackages = {"com.liu.susu","com.liu2.susu"})
- 好了,上个问题到这里解决了,开始mapper问题了。
Description:
Field dogMapper in com.liu2.susu.message.service.DogServiceImpl required a bean of type 'com.liu2.susu.message.mapper.DogMapper' 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 'com.liu2.susu.message.mapper.DogMapper' in your configuration.
4.1.3 问题3->@MapperScan
4.1.3.1 启动类中 @MapperScan
- 上面的原因:
在接口类上添加了@Mapper,在编译之后会生成相应的接口实现类,但是@ComponentScan不扫描@Mapper - 所以用注解
@MapperScan
解决问题@MapperScan
注解的作用是:指定要编译成接口实现类的包路径,在编译完成后这个包下的所有接口都会生成相应的接口实现类。
@MapperScan("com.liu2.susu.message.mapper")
- 好了,到此就完美解决了!,再看看接口文档
4.1.3.2 配置文件中 @MapperScan
- 上面的扫描mapper包也可以加到配置文件中,去form-start模块中找到mybatis或mybatis-plus的配置类,添加上去即可,如下
//@MapperScan("com.liu.susu.**.mapper")
@MapperScan(basePackages={"com.liu.susu.**.mapper","com.liu2.susu.message.mapper"})
- 或者用
**
匹配
@MapperScan("com.**.susu.**.mapper")
4.2 把 Dogcontroller 移回原包
- 上面问题解决之后,测试没问题的话,可以移回去,问题也是肯定解决了的,这里我就不演示了。
5. 开发建议
- 看上面的问题,虽然肯定可以解决,但是毕竟有点麻烦,如果统一包名那就没这么多麻烦事,保持原本的注解配置即可,所以,如果是同一个项目,项目的包名尽量保持一致,约束大于配置,还是要规范些好
好了,完美陈述了!