You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Quarkus传统RestEasy中@RestClient与Mock共存引发依赖不满足错误

Quarkus传统RestEasy中@RestClient注入冲突问题(存在接口实现类时的依赖不满足错误)

在Quarkus传统RestEasy环境下,当通过@RestClient注入标注了@RegisterRestClient的FlightGateway接口时,若项目中存在该接口的实现类FlightMock,会触发UnsatisfiedResolutionException(依赖不满足)错误。移除FlightMock对FlightGateway的实现后,应用可正常启动;且该问题仅出现在传统RestEasy中,RestEasy Reactive无此异常。

相关代码示例

网关接口(FlightGateway)

@RegisterRestClient(configKey = "gateway")
public interface FlightGateway {
    @Path("/esb/flight/bookflight/v1")
    @POST
    BookFlightResp bookFlight(BookFlightReq req);
}

服务实现类(FlightServiceImpl)

public class FlightServiceImpl implements FlightService {
    @RestClient
    FlightGateway flightGateway;

    @Override
    public BookFlightRply flightBooking(BookFlight req) {
        BookFlightRply rply = flightGateway.bookFlight(req);
        return rply;
    }
}

Mock实现类(FlightMock)

public class FlightMock implements FlightGateway {
    @Override
    public BookFlightResp bookFlight(BookFlightReq req) {
        // Mock逻辑
        return resp;
    }
}

报错信息

[error]: Build step io.quarkus.arc.deployment.ArcProcessor#validate threw an exception: javax.enterprise.inject.spi.DeploymentException: javax.enterprise.inject.UnsatisfiedResolutionException: Unsatisfied dependency for type com.as.flight.integration.gateway.FlightGateway and qualifiers [@RestClient]
- java member: com.as.flight.service.FlightServiceImpl#FlightGateway
[[1;31mERROR[m]     - declared on CLASS bean [types=[com.as.flight.service.FlightServiceImpl, java.lang.Object, com.as.flight.service.FlightService], qualifiers=[@Default, @Any], target=com.as.flight.service.FlightServiceImpl]

问题原因

传统RestEasy的RestClient扩展在处理带有@RegisterRestClient的接口时,若发现该接口存在自定义实现类(如FlightMock),会停止自动生成RestClient代理Bean。此时CDI容器中仅存在无@RestClient限定符的FlightMock Bean,而注入点要求的是带有@RestClient限定符的FlightGateway实例,因此触发依赖解析失败。

而RestEasy Reactive的RestClient扩展逻辑不同,即使接口存在自定义实现类,仍会生成带@RestClient限定符的代理Bean,因此不会出现冲突。

解决方案

方案1:为Mock类添加限定符并标记为CDI Bean

给FlightMock添加自定义限定符,同时标记为CDI Bean,确保其与RestClient代理Bean的限定符区分开:

// 自定义限定符
@Qualifier
@Retention(RUNTIME)
@Target({TYPE, METHOD, FIELD, PARAMETER})
public @interface Mock {}

// 在FlightMock上使用
@ApplicationScoped
@Mock
public class FlightMock implements FlightGateway {
    // ... 实现逻辑
}

此时注入点明确使用@RestClient,CDI容器会正确匹配RestClient代理Bean。

方案2:将Mock类放在测试目录中

如果FlightMock仅用于测试场景,直接将其移至src/test/java目录下。生产环境构建时不会扫描测试目录的类,因此不会干扰RestClient代理Bean的生成。

方案3:通过Quarkus Profile控制Mock类的加载

为FlightMock添加@Profile注解,指定仅在特定Profile(如测试环境)下启用该Bean:

@ApplicationScoped
@Profile("test")
public class FlightMock implements FlightGateway {
    // ... 实现逻辑
}

这样在生产环境(默认Profile)下,FlightMock不会被注册为CDI Bean,RestClient代理Bean可正常生成。

方案4:使用@Alternative替代默认实现

将FlightMock标记为@Alternative并设置优先级,在需要Mock的场景下启用:

@ApplicationScoped
@Alternative
@Priority(1)
public class FlightMock implements FlightGateway {
    // ... 实现逻辑
}

然后在application.properties中配置启用Alternative:

quarkus.arc.alternatives.enabled=com.as.flight.integration.mock.FlightMock

此方式适用于需要在特定环境替换RestClient实现的场景。

内容的提问来源于stack exchange,提问作者topgun

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.15 21:45:54