我有一个CDI bean,并且将拦截器添加到该bean的一种方法中。
如果此bean没有默认构造函数(我使用构造函数注入(inject))。
在运行时,出现异常

java.lang.Class.newInstance0(Class.java:357)
java.lang.Class.newInstance(Class.java:325)
org.apache.webbeans.proxy.javassist.JavassistFactory.createProxy(JavassistFactory.java:79)
org.apache.webbeans.proxy.ProxyFactory.createProxy(ProxyFactory.java:241)
org.apache.webbeans.proxy.ProxyFactory.createDependentScopedBeanProxy(ProxyFactory.java:412)
org.apache.webbeans.component.AbstractInjectionTargetBean.createDefaultInstance(AbstractInjectionTargetBean.java:140)
org.apache.webbeans.component.AbstractInjectionTargetBean.createInstance(AbstractInjectionTargetBean.java:116)
org.apache.webbeans.component.AbstractOwbBean.createNewInstance(AbstractOwbBean.java:233)
org.apache.webbeans.portable.creation.AbstractProducer.produce(AbstractProducer.java:77)
org.apache.webbeans.component.InjectionTargetWrapper.produce(InjectionTargetWrapper.java:136)

如果我在此bean中添加默认构造函数,或删除拦截器,那就可以了。
实际上,我可以使用场注入(inject)来解决这个问题。

但我想知道:如果添加默认构造函数,则意味着此bean有两个构造函数-一个是非参数构造函数,另一个是@Inject ed参数。在这种情况下(使用拦截器),容器将两次创建实例吗?

编辑:我使用Tomee1.5,而WebShpere8.5与Tomee1.5相同
并且似乎GlassFish3.1.2没有此问题。

编辑:我在Tomee用户论坛中找到了一个答案,即
CDI容器将为您的bean调用@Inject注释的ct,但将使用默认的ct创建代理。
因此,我认为这意味着如果要使用构造函数注入(inject),则还需要一个默认的构造函数才能实现代理。

编辑:
  • 根据http://docs.jboss.org/weld/reference/latest/en-US/html/injection.html#d0e1443
    除非bean具有默认范围@Dependent,否则容器必须通过代理对象间接调用所有注入(inject)到bean的引用。
  • 根据//openejb.979440.n4.nabble.com/RequestScoped-CDI-constructor-td4661541.html
    CDI容器将为您的bean调用@Inject注释的构造函数,但将使用默认的构造函数创建代理。因此,所有“NormalScoped”(@ RequestScoped @SessionScoped @ApplicationScoped @ConversationScoped)Bean都需要默认构造函数,因为它们将始终被代理。
  • 如果bean使用拦截器,则根据错误消息,OpenWebBean使用Proxy处理拦截器,因此被拦截的类必须具有默认构造。但是Weld使用子类作为拦截器和装饰器。 https://issues.jboss.org/browse/WELD-437?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel子类解决方案优于代理,因为它避免了许多问题,例如:没有no-arg构造函数的拦截类和对代理实例的字段访问。
    因此,如果我使用Tomee和Websphere,则需要一个默认ct,而GlassFish则不需要。

    谢谢brandizzi,这是我的第一个问题。感谢您的帮助。
    而且似乎我无法回答自己的问题并发布两个以上的链接
    没有10个声誉,所以我在这里进行了编辑。
  • 最佳答案

    CDI specification中所述,具有绑定(bind)拦截器的CDI bean必须是可代理的(如unproxyable bean types所定义),该声明还声明proxyblebean是具有无参数的非 private 构造函数的类。

    关于default - 具有拦截器的CDI bean是否应具有默认构造函数?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/15637391/

    10-15 23:33