【发布时间】:2010-12-25 12:38:18
【问题描述】:
在 EJB 3.1 中,我可以在为该 bean 获得的 TimerService 实例上使用 TimerService#getTimers() 获取特定 bean 的所有计时器。
然而,我真正需要的是系统范围的版本。 IE。我想要一份 EJB 容器中所有计时器的列表。
这样的事情可能吗?
【问题讨论】:
在 EJB 3.1 中,我可以在为该 bean 获得的 TimerService 实例上使用 TimerService#getTimers() 获取特定 bean 的所有计时器。
然而,我真正需要的是系统范围的版本。 IE。我想要一份 EJB 容器中所有计时器的列表。
这样的事情可能吗?
【问题讨论】:
在 EJB 3.1 中根本没有用于此的官方 API。
如果您只使用注解和/或接口来标记超时方法,您可以对类路径上的所有类进行运行时遍历,并检查此注解或接口是否存在。这至少会给你理论上可以有与之关联的计时器的bean。
不幸的是,这仍然不会为您提供这些 bean 的实际计时器。在 EJB 3.1 中,只能从会话上下文中请求时间信息,您似乎已经知道,会话上下文对于每个 bean 都是私有的。这意味着只有 bean 本身才能看到它有哪些计时器。
作为 Nayan 建议的替代方案,您可以让您的 bean 实现一种方法来为您提供此信息。然后,您可以使用接口或自定义注释标记此方法。
在您对所有计时器类的全系统扫描中,您首先尝试发现所有可以与它们关联的计时器的bean,然后尝试找出它们是否具有所需的注释或接口。如果他们没有后一种情况,您可以记录警告。这种方法的优点是计时器不太可能漏掉。
还有另一种方法,但非常脆弱,是侵入容器保存的任何私有结构以存储计时器信息。对于持久计时器,至少有可以检查的持久存储,并且容器中的某处必须有您所追求的结构。它必须在那里,因为容器本身必须意识到这一点。通常一个容器有一些私有的 API 来达到这个目的,你可以通过反射技巧来破解它。
容器也可以为此提供专有 API。例如。在 Java EE 5 中,不可能在 Servlet 容器中进行编程登录,但 JBoss AS 有一个专有的 API 可以让您做到这一点。
【讨论】:
TimerService 与 EJB 的分离。
EJB 3.2 有一个名为“getAllTimers()”的方法。
https://docs.oracle.com/javaee/7/api/javax/ejb/TimerService.html#getAllTimers--
说明: 返回与打包调用者 bean 的同一模块中的 bean 关联的所有活动计时器。其中包括以编程方式创建的计时器和自动创建的计时器。
【讨论】:
以下是获取系统所有现有计时器信息的示例代码片段。
//---
private void viewSystemTimers(){
Collection<Timer> allTimers = sessionContext.getTimerService().getTimers();
Iterator<Timer> iterator = allTimers.iterator();
while (iterator.hasNext()) {
Timer timer = (Timer) iterator.next();
System.out.println("SYSTEM TIMER : "+timer.getInfo());
}
}
//---
【讨论】:
您只能看到自己班级的计时器。使用 EJB 调度程序,您无法列出应用程序的所有计时器。
@Resource
private TimerService timerService;
for (Timer timer : timerService.getTimers()) {
// do anything
}
使用 Quartz,您可以通过 Scheduler.getJobNames/triggerNames 获取应用程序的所有作业/触发器。
【讨论】: