CDI对象不可与注入的构造函数一起代理

Ste*_*ote 12 java dependency-injection cdi weld

尝试将参数注入CDI bean(ApplicationScoped)的构造函数时,遇到以下问题:

Caused by: org.jboss.weld.exceptions.UnproxyableResolutionException: WELD-001435: Normal scoped bean class xx.Config is not proxyable because it has no no-args constructor - Managed Bean [class xx.Config] with qualifiers [@Default @Named @Any].
    at org.jboss.weld.bean.proxy.DefaultProxyInstantiator.validateNoargConstructor(DefaultProxyInstantiator.java:50)
    at org.jboss.weld.util.Proxies.getUnproxyableClassException(Proxies.java:217)
    at org.jboss.weld.util.Proxies.getUnproxyableTypeException(Proxies.java:178)
Run Code Online (Sandbox Code Playgroud)

但是,我在类上确实有一个可注入的构造函数:

@Inject
public Config(ConfigLocator configLocator) {
    defaultConfigPath = configLocator.getPath();
    doStuff();
}
Run Code Online (Sandbox Code Playgroud)

使用默认构造函数,变量注入和postconstruct方法,这些都可以正常工作,但是在这种情况下,我更喜欢使用构造函数注入。

有什么想法怎么了?

Vla*_*sky 5

我们解决了将类拆分为接口和实现的类似问题。在您的情况下,如下所示:

public interface Config
{
  // API here
}

@ApplicationScoped @Priority(0)
public class ConfigImpl implements Config
{
  @Inject
  public ConfigImpl(ConfigLocator configLocator) { ... }

  // API implementation here
}
Run Code Online (Sandbox Code Playgroud)


Ani*_* B. 5

这个例子可能会帮助你:

@ApplicationScoped
public class Config {

    private String defaultConfigPath;  

    @Inject
    public Config(ConfigLocator configLocator) {
       this.defaultConfigPath = configLocator.getPath();
       doStuff();
    }

    // create a no-args constructor which is required for any scoped bean.
    public Config() {
    }

}
Run Code Online (Sandbox Code Playgroud)

bean中需要有一个公共的无参数构造函数@ApplicationScoped

注意:此类的 bean 将仅创建一次,并在应用程序的整个生命周期中维护。该 bean 将在所有托管 bean 之间共享。@ApplicationScoped beans本质上是单例的。

提到的问题:

Caused by: org.jboss.weld.exceptions.UnproxyableResolutionException: WELD-001435: Normal scoped bean class xx.Config is not proxyable because it has no no-args constructor - Managed Bean [class xx.Config] with qualifiers [@Default @Named @Any].
Run Code Online (Sandbox Code Playgroud)

可能的原因是,需要一个非依赖作用域 bean 来为 CDI 提供一个公共的无参数构造函数,以便它可以在运行时获取所需的代理 bean。


cov*_*ner 4

实现需要非私有、无参数构造函数来创建托管 bean 的代理。您不会因为存在非私有、无参数构造函数而失去注入构造函数的功能。

容器使用代理来允许拦截、修饰等操作,并在取消引用 bean 时检索正确的上下文实例。它还需要允许 bean 之间的循环注入。