maven模块循环依赖解决方案
maven模块循环依赖解决方案
maven模块循环依赖解决方案
模块循环依赖场景
在大型java工程中,通常使用maven module
划分不同模块,并使用<dependency>
标签引用模块。
A模块已经依赖了B模块,后续开发时,又想在B模块中使用A模块的service,此时引入A模块,在启动时就会出现循环依赖报错。此处AB模块都是项目自开发的模块。
出现原因
通常由于前期的模块划分不合理。
解决方案
重新划分模块,相当于重构,但在大型项目中代价较大。 轻量级的方案,可以使用spring上下文容器读取其他模块的beanName解决。如需要动态加载不同模块,可以增加接口定义+不同实现的方式。
具体编码案例
接口定义
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
// 在B模块定义接口
public interface BModuleHandler {
// 在接口中使用枚举类,定义业务编码和回调的spring bean名称。关联的内容相对内聚,实现在一处地方统一定义和使用,避免使用额外的常量类定义
public enum HdlEnum {
// 其他模块,实现BModuleHandler接口的方法handle,并以硬编码方式,在B模块此处添加注册自定义处理器
A_MODULE_HDL("a1", "aModuleService");
private String code;
private String beanName;
HdlEnum(String code, String beanName) {
this.code = code;
this.beanName = beanName;
}
// 回调:在B模块中,使用BModuleHandler.HdlEnum.getHdlByCode(code).handle()方式,调用其他模块
public static BModuleHandler getHdlByCode(String code) {
for (BModuleHandler.HdlEnum v : values()) {
if (v.code.equals(code)) {
// 从上下文获取service,规避模块划分和引用不合理导致的循环依赖冲突问题
return SpringBeanUtils.getBean(v.beanName);
}
}
return null;
}
}
// 处理方法,具体实现在其他模块
Boolean handle();
}
调用者
1
2
3
4
5
6
7
8
9
// B模块已经被A模块依赖,但又想使用A模块的service资源,再次引用会出现循环依赖报错。可以使用回调方式解决。
@Service
public class BModuleService {
public void do() {
BModuleHandler someModuleHdl = BModuleHandler.HdlEnum.getHdlByCode(code);
someModuleHdl.handle();
}
}
实现者
1
2
3
4
5
6
7
8
9
// A模块依赖B模块,实现BModuleHandler接口和handle方法
@Service("aModuleService")
public class AModuleService implements BModuleHandler {
@Override
Boolean handle() {
// 在B模块中进入该方法后,即可使用A模块的其他service
}
}
本文由作者按照 CC BY 4.0 进行授权