我有一个 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 带注释的 ct,但将使用默认 ct 来创建代理。所以,我认为这意味着如果你想使用构造函数注入,你还需要一个默认构造函数来进行代理。
编辑:
根据http://docs.jboss.org/weld/reference/latest/en-US/html/injection.html#d0e1443 ,除非bean具有默认范围@Dependent,否则容器必须通过间接所有注入的bean引用一个代理对象。
根据 //openejb.979440.n4.nabble.com/RequestScoped-CDI-constructor-td4661541.html CDI 容器将为您的 bean 调用 @Inject 带注释的构造函数,但将使用默认构造函数来创建代理。因此,所有 'NormalScoped' (@RequestScoped @SessionScoped @ApplicationScoped @ConversationScoped) bean 都需要默认构造函数,因为它们总是会被代理。
如果一个bean使用了interceptor,根据报错信息,OpenWebBean使用Proxy来处理interceptor,所以被拦截的类必须有default构造。但是 Weld 使用拦截器和装饰器的子类。https://issues.jboss.org/browse/WELD-437?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel 子类化解决方案优于代理,因为它避免了处理许多问题例如:在代理实例上没有无参数构造函数和字段访问的拦截类。所以,如果我使用 Tomee 和 Websphere,它需要一个默认 ct,但 GlassFish 不需要。
谢谢brandizzi,这是我的第一个问题。谢谢您的帮助。似乎我无法回答我自己的问题并发布两个以上没有 10 个声誉的链接,所以我在这里进行了编辑。