Hello, all 。这里请教一个 Spring 循环依赖的问题。
我定义了三个类:配置类 AppConfig 、业务类 AppBiz 、自动装载类 AppAutoConfiguration 。三个类的简化代码如下所示:
// AppConfig
@ConfigurationProperties(prefix="app")
public class AppConfig
{
private String version = “1.0.0”;
}
// AppBiz
public class AppBiz {
private final AppConfig config;
public AppBiz(AppConfig config){
this.config = config;
}
}
// AppAutoConfiguration
@EnableConfigurationProperties(AppConfig.class)
public class AppAutoConfiguraion{
@Resource
private AppConfig config;
@Bean
public AppBiz buildAppBiz(){
return new AppBiz(config);
}
}
当我将这个项目作为一个 jar 包提供给其他系统的时候,希望通过读取配置文件 app.version 自动装载,实现一些逻辑。
现在的情况是,我不在配置文件里写 app.version
时,项目可以正常启动,自动装配 AppAutoConfiguration ;当我在配置文件中加上 app.version
,自动装载配置类就报循环依赖的问题。提示是 AppBiz 和 AppConfig 循环依赖。
有大哥能看下上面的代码有什么问题吗。
2
BBCCBB 360 天前
你这只有 AppBiz 依赖 appconfig, appconfig 也没有依赖 appBiz 呀.
|
4
ak1ak OP @BBCCBB #1 加上 `@Lazy` 才显示具体的循环依赖信息;不加 `@Lazy` 会提示「创建 AppAutoConfiguration Bean 失败,这个 Bean 中依赖的其他 Bean 正在创建,可能有没有解决的循环依赖 」:-(
|
5
ak1ak OP @zoharSoul #3 你的意思是将 AppBiz 改成一个 `@Component`,然后通过 `@Autowired` 的方式注入 AppConfig 吗。这个应该行不通,我这边想做的是通过在 AppAutoConfiguration 控制是否加载 AppBiz 。也就是 buildAppBiz 方法上会有 `@Conditional` 条件
|
7
ak1ak OP @retanoj #6 不行的。这个 AppAutoConfiguration 这个类要作为一个自动装配模块提供给其他系统调用,如果通过 `@Component` 进行标记,其他系统要通过 componentScan 扫描这个类路径,和自动装配的初衷不符。理想情况下是在其他系统通过配置文件,条件化地加载 AppAutoConfiguration 中的各个组件。
|
8
fulln 359 天前
spring 当处理构造器注入 bean 的时候,会出现这种问题, 你试下成员变量用注解注入 bean
|
9
retanoj 359 天前
@Configuration
@EnableConfigurationProperties(AppConfig.class) class AppAutoConfiguraion{} 使用方 @Autowired AppAutoConfiguraion appAutoConfiguraion; |
10
cppc 359 天前
感觉遗漏了信息,上个 demo 看看
|
11
ak1ak OP @cppc #10 demo 代码在 https://pastebin.ubuntu.com/p/bcS3Kkq797/。使用的第三方库是 jasypt-spring-boot 。这个库的作用是读取一个 encryptablePropertyResolver 的 Bean 实例之后,通过判断配置的前缀是否是指定前缀,如果是,根据 EncryptablePropertyResolver#resolvePropertyValue 进行解析。(我感觉是这个依赖的问题,EncryptablePropertyResolver 依赖一个 AppConfig 的 Bean ,但是先要初始化一个 EncryptablePropertyResolver 的 Bean 来判断是否需要对 AppConfig 配置进行解密,因此出现了循环依赖。隐约感觉是这个问题,不知道怎么解决。
|
12
ediron 359 天前
|
13
YCNQc647Cfngdp89 359 天前
改成 buildAppBiz(AppConfig config),把 resource 注解的 bean 删掉
|
14
258 359 天前
这个没有循环依赖呀
|
15
running17 359 天前
单从代码看不出来有问题,建议把报错信息脱敏一下放上来看看
|
16
ak1ak OP @258 @running17 从这个代码的确看不出为什么会有循环依赖,所以可能就是 #11 分析的问题。
通过 `@Resource` field 注入提示的错误: ![setter 注入失败]( https://s3.bmp.ovh/imgs/2023/07/12/35f7b818c71647d5.png) 通过构造函数或者 `@Resource` + `@Lazy` 注入提示的错误: ![构造函数注入失败]( https://s3.bmp.ovh/imgs/2023/07/12/a8994322e6668044.png) |
17
wanghaoxu 359 天前
简单调试了一下,循环依赖大概是这个问题
encryptablePropertyResolver 依赖 config config 依赖 application.properties 文件,application.properties 文件依赖你用的那个加解密组件, 加密组件又依赖 properties 文件 建议新建一个 xxx.propertiesconfig 文件,这里面写初始化加解密组件的配置,让 config 依赖 xxx.properties 文件(使用 @PropertySource("classpath:xxx.properties")指定配置文件),猜测 xxx.propertiesconfig 文件不会依赖那个加密文件,不会参与加解密,试了下没有循环依赖问题了,你可以试试 |