EJB @Singleton焊接代理实例的数量稳步增加

时间:2018-06-20 17:41:18

标签: java-ee ejb cdi

我们有一个EJB @Singleton,因为我们可以从中受益:

  • @DependsOn
  • @ Startup,@ PostConstruct等...
  • @LocalBean,注入诸如ManagedScheduledExecutorService之类的资源
  • @ConcurrencyManagement

EJB Singleton是EAR部署的一部分。为了能够在不属于EJB或CDI范围的遗留代码中使用它,我们目前使用CDI.current().select(<type-of-singleton-EJB>).get()之类的东西手动注入它。

现在,我们注意到该单例的$Proxy$_$$_Weld$EnterpriseProxy$$$$viewxxx实例数量在稳定增长,我认为这是因为对于CDI,EJB @Singleton位于@Dependent中伪作用域,因此所有这些手动注入的实例的生存时间与我们的旧代码类(可能与应用程序生存的时间)一样长。 请注意,只是增加了代理实例的数量,而不是实际实例,而仅仅是一个。

似乎有几种解决方案:

  1. 也用@ApplicationScoped注释@Singleton EJB:这项工作有效,只有一个代理实例和每个视图实例
  2. 用JNDI查找替换手动CDI选择:这也有效,视图只有一个实例
  3. 使用CDI.current.destroy()删除代理实例:尚未尝试过,因为在我们的场景中实现起来并不容易
  4. 将遗留代码也转换为EJB或CDI管理的bean,并执行常规的@Inject:@Singleton EJB上可能仍需要@ApplicationScoped吗?

所以我的问题是:观察是完全正确的吗,可以同时使用EJB @Singleton和CDI @ApplicationScoped注释bean吗?哪种方法更可取?

1 个答案:

答案 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吗?

正如您现在所了解的那样,这不是一件好事,而是您经常这样做吗,因为@SingletonApplicationScoped之间的映射看起来比@Dependent更自然。 我会说这是解决您问题的最佳方法。

  

...因此,所有那些手动注入的实例的寿命与我们的旧代码类(可能与应用程序的寿命一样长)一样。

好吧,如果您重复执行该代码,并且在每次运行时都重新注入它,那么就会出现问题。由于遗留代码不是CDI bean(根据您所说的是非上下文实例),因此必须创建一个每次都要移交的新代理。您还需要处理依赖的bean处理方法-与您提出的第三个解决方案类似。