首页 > 解决方案 > 如果 bean 没有无参数构造函数,如何将 @Normal (@ApplicationScoped) bean 注入 @Dependent 范围

问题描述

这篇文章与我的一个较旧的 SO Post相关,其中我试图了解 WELD 的无参数构造函数的要求。

现在,我正试图弄清楚 CDI 中是否有办法将@ApplicationScopedbean (@Normal) 注入@Dependent范围。从我从 WELD 中读到的内容来看,要求是有一个非私有的无参数构造函数是可代理的。但是,我无法控制 bean 定义,因为它是由库提供的。我的代码正在执行以下操作:

    @Produces
    @ApplicationScoped
    @Named("keycloakAdmin")
    public Keycloak getKeycloakAdminClient(@Named("keycloakDeployment") final KeycloakDeployment deployment) {
        String clientId = deployment.getResourceName();
        Map<String, Object> clientCredentials = deployment.getResourceCredentials();

        // need to set the resteasy client connection pool size > 0 to ensure thread safety (https://access.redhat.com/solutions/2192911)
        ResteasyClient client = new ResteasyClientBuilder().connectionPoolSize(CONNECTION_POOL_SIZE).maxPooledPerRoute(CONNECTION_POOL_SIZE)
                .defaultProxy("localhost",8888)
                .build();

        KeycloakBuilder builder = KeycloakBuilder.builder()
                .clientId(clientId)
                .clientSecret((String) clientCredentials.get(CredentialRepresentation.SECRET))
                .realm(deployment.getRealm())
                .serverUrl(deployment.getAuthServerBaseUrl())
                .grantType(OAuth2Constants.CLIENT_CREDENTIALS)
                .resteasyClient(client);

        return builder.build();
    }



    // error thrown here that cannot inject @Normal scoped bean as it is not proxyable because it has no no-args constructor
    @Produces
    @Dependent
    @Named("keycloakRealm")
    public RealmRepresentation getKeycloakRealm( @Named("keycloakAdmin") final Keycloak adminClient ){
        // error thrown here that cannot inject @Normal scoped bean as it is not proxyable because it has no no-arg
        return adminClient.realm(resolveKeycloakDeployment().getRealm()).toRepresentation();
    }

问题是我不控制Keycloakbean;它由图书馆提供。因此,我无法为 bean 提供无参数构造函数。

这是否意味着不可能做到?有没有可以使用的解决方法?这似乎是 WELD 的一个重大限制,特别是在涉及到@Produce3rd 方 bean 时。

我的目标是为应用程序提供一个Keycloakbean,因为它是线程安全的,并且只需要初始化一次。但是,我希望能够将其注入到非应用程序范围的 bean 中。

有一个@Singleton范围可以解决我的问题,但如果@Singleton适用于这种情况,这两个不同范围的目的是什么?在什么情况下需要非代理单例(@Singleton)与代理单例(@ApplicationScoped)?还是@Singleton针对整个容器,而@ApplicationScoped仅针对应用程序(WAR)?它如何适用于 EAR 或多只耳朵?

标签: cdiweldjboss-weld

解决方案


推荐阅读