带拦截器的CDI bean是否应该有默认构造函数?

时间:2013-03-26 12:44:11

标签: default cdi interceptor constructor-injection

我有一个CDI bean,并且拦截器被添加到这个bean的一个方法中。 如果这个bean没有默认构造函数(我使用构造函数注入)。 在运行时,我得到了异常

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中添加一个默认构造函数,或者删除拦截器,那就没问题了。 事实上,我可以使用现场注入来处理这个问题。

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

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

编辑:我在Tomee用户论坛中找到了答案 CDI容器将为您的bean调用@Inject annotated ct,但将使用默认ct来创建代理。 所以,我认为这意味着如果你想使用构造函数注入,你还需要一个默认的构造函数来代理。

修改

  1. 根据http://docs.jboss.org/weld/reference/latest/en-US/html/injection.html#d0e1443 除非bean具有默认范围@Dependent,否则容器必须通过代理对象间接地对bean进行所有注入引用。

  2. 根据//openejb.979440.n4.nabble.com/RequestScoped-CDI-constructor-td4661541.html CDI容器将为您的bean调用@Inject带注释的构造函数,但将使用默认构造函数来创建代理。因此,所有'NormalScoped'(@RequestScoped @SessionScoped @ApplicationScoped @ConversationScoped)bean都需要默认构造函数,因为它们将始终被代理。

  3. 如果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个声誉,所以我在这里编辑。

1 个答案:

答案 0 :(得分:0)

CDI specification中所述,具有绑定拦截器的CDI bean必须是可代理的,如unproxyable bean types中所定义,此外还声明可代理bean是具有非私有构造函数的类没有参数。