我们有一个EJB @Singleton,因为我们可以从中受益:
EJB Singleton是EAR部署的一部分。为了能够在不属于EJB或CDI范围的遗留代码中使用它,我们目前使用CDI.current().select(<type-of-singleton-EJB>).get()
之类的东西手动注入它。
现在,我们注意到该单例的$Proxy$_$$_Weld$EnterpriseProxy$
和$$$viewxxx
实例数量在稳定增长,我认为这是因为对于CDI,EJB @Singleton位于@Dependent中伪作用域,因此所有这些手动注入的实例的生存时间与我们的旧代码类(可能与应用程序生存的时间)一样长。
请注意,只是增加了代理实例的数量,而不是实际实例,而仅仅是一个。
似乎有几种解决方案:
所以我的问题是:观察是完全正确的吗,可以同时使用EJB @Singleton和CDI @ApplicationScoped注释bean吗?哪种方法更可取?
答案 0 :(得分:1)
首先,不一定将EJB @Singleton
转换为CDI中的@Dependent
bean。如果未添加其他CDI范围,这只是Weld的默认行为。
以下是EJB如何“映射”到CDI范围的列表:
@Stateless
-> @Dependent
@Stateful
-> @SessionScoped
@Singleton
-> @Dependent
或 @ApplicationScoped
@Singleton
-> @Dependent
(只是在每次注入时都会创建代理,否则显然会委派给同一基础EJB单例)@Singleton
+ @ApplicationScoped
-> @ApplicationScoped
这是link to spec的描述。
为了能够在不属于EJB或CDI范围的遗留代码中使用它,我们目前使用
CDI.current().select(...).get()
之类的东西手动注入它。
如果我正确理解它,则可以使用CDI.current()
从应用程序中的各个位置检索此EJB单例。现在,这可能很棘手,因为CDI.current()
的定义不正确,并试图“猜测”要使用哪个bean管理器来检索bean。如果我们正在谈论EAR部署,这将变得更加棘手。理想情况下,如果可能的话,您最好避免使用CDI.current()
。
现在,我们注意到我们拥有的那个单例的$ Proxy $ _ $$ _ Weld $ EnterpriseProxy $和$$$ viewxxx实例的数量稳步增长,
在您的情况下,只有@Singleton
批注,因此代理CDI的行为类似于@Dependent
范围。因此,每次注射都要新注射一次(在您的情况下,通过CDI.current()
完成)。但是您要注入非上下文对象(不是为了简化它而没有注入到bean中),因此您还需要照顾bean并在不再需要它时将其处理。
...可以同时使用EJB @Singleton和CDI @ApplicationScoped注释Bean吗?
正如您现在所了解的那样,这不是一件好事,而是您经常这样做吗,因为@Singleton
和ApplicationScoped
之间的映射看起来比@Dependent
更自然。 我会说这是解决您问题的最佳方法。
...因此,所有那些手动注入的实例的寿命与我们的旧代码类(可能与应用程序的寿命一样长)一样。
好吧,如果您重复执行该代码,并且在每次运行时都重新注入它,那么就会出现问题。由于遗留代码不是CDI bean(根据您所说的是非上下文实例),因此必须创建一个每次都要移交的新代理。您还需要处理依赖的bean处理方法-与您提出的第三个解决方案类似。