使用 Spring 和 Micronaut,有非常简洁的方法可以根据应用程序运行的环境/配置文件来注入不同的 bean。我正在尝试对 Quarkus 做同样的事情。
我读过这篇文章: https: //quarkus.io/blog/quarkus-dependency-injection/。这个 StackOverflow 帖子中提到了这个过程:How can I override a CDI bean in Quarkus for test? 。最后一篇文章说,“在测试目录中创建 bean”。
我的问题略有不同。我想在“开发”时注入一个bean。在生产中,我想注入默认的 bean。从文档中,我看不出有什么方法可以让应用程序做出这种区分。
如果我有一个像这样的默认类:
@DefaultBean
@ApplicationScoped
class ProdProvider : SomeProvider {}
Run Code Online (Sandbox Code Playgroud)
我想像这样覆盖它:
@Alternative
@Priority(1)
class DevProvider : SomeProvider {}
Run Code Online (Sandbox Code Playgroud)
我怎样才能只在开发模式下发生这种情况?
在一种情况下,我有一个凭据提供程序类,用于在本地开发时设置 Google 的 PubSub 模拟器。在生产中,我使用一个实现相同接口的类,但它是一个真正的凭据提供程序。导致我问这个问题的特殊情况是一个实现一种方法的类:
@ApplicationScoped
class VaultLoginJwtProvider : LoginJwtProvider {
@ConfigProperty(name = "vault.tokenPath")
private val jwtPath: String? = null
companion object {
val logger: Logger = LoggerFactory.getLogger("VaultTokenProvider")
}
override fun getLoginJwt(): Optional<String> {
logger.info("Using Vault Login JWT")
return try {
Optional.of(String(Files.readAllBytes(Paths.get(jwtPath))).trim { it <= ' ' })
} catch (e: Exception) {
logger.error("Could not read vault token at $jwtPath")
logger.error(e.printStackTrace().toString())
Optional.empty()
}
}
}
Run Code Online (Sandbox Code Playgroud)
该类通过构造函数注入注入到另一个类中:
@Singleton
class JwtServiceImpl(
@RestClient val vaultClient: VaultClient,
@Inject val loginJwtProvider: LoginJwtProvider
) {
private var serviceJwt: String? = null
companion object {
val logger: Logger = LoggerFactory.getLogger("JwtServiceImpl")
}
private fun getLoginToken(): String? {
val vaultLogin = VaultLogin(
role = "user-service",
jwt = loginJwtProvider.getLoginJwt().get()
)
val loginResponse = vaultClient.login(vaultLogin)
return loginResponse.auth.clientToken
}
}
Run Code Online (Sandbox Code Playgroud)
我想在开发过程中注入更多的“模拟”类,只返回静态字符串。我可以使用ProfileManager.getActiveProfile(),但这让我将开发问题融入到我的逻辑中。我觉得这在我编译的生产代码中没有任何地位。
在 Micronaut 中可以通过使用注释来实现这一点@Requires(env = ["dev", "test"])。我确实简要地了解了使用@Produces,但 Oracle EE 文档对我来说似乎有点难以掌握。如果这是解决方案,我会深入研究。
小智 9
如果其他人遇到这种情况,请按以下方法操作:https ://quarkus.io/guides/cdi-reference#enabling-beans-for-quarkus-build-profile
例如:
import javax.enterprise.inject.Produces;
import com.oi1p.common.EmailSender;
import com.oi1p.common.ErrorEmailSender;
import com.oi1p.common.LogOnlyEmailSender;
import io.quarkus.arc.DefaultBean;
import io.quarkus.arc.profile.IfBuildProfile;
@ApplicationScoped
public class Producers {
@Produces
@IfBuildProfile("dev")
public EmailSender logOnlyEmailSender() {
return new LogOnlyEmailSender();
}
@Produces
@DefaultBean
public EmailSender errorEmailSender() {
// TODO: implement a real email sender. This one explodes when poked.
return new ErrorEmailSender();
}
}
Run Code Online (Sandbox Code Playgroud)