我在EJB Stateless上使用JBoss AS 7和Schedule方法。我的问题是,即使EJB是一个无状态的,它保持其状态,这给我带来了麻烦。这是一个例子:
计时器:
@Stateless
public class TestTimer {
@Inject HelloWorldService helloWorld;
@SuppressWarnings("unused")
@Schedule(second="*/10", minute="*", hour="*", info="MyTimer")
private void execute() {
System.out.println(helloWorld.sayHello());
System.out.println(this.toString() + " "+ helloWorld.toString());
}
}
注入的HelloWorldService:
public class HelloWorldService {
public String sayHello() {
return "Hello World!";
}
}
我希望每次定时器运行时,行System.out.println(this.toString() + " "+ helloWorld.toString());
会打印一个不同的时间,因为每次都会有一个新的TestTimer
实例,但我错了:
16:43:50,003 INFO [stdout] (EJB default - 3) foo.service.TestTimer@4a56936f foo.service.HelloWorldService@79e98289
16:44:40,022 INFO [stdout] (EJB default - 1) foo.service.TestTimer@4a56936f foo.service.HelloWorldService@79e98289
我做错了什么,这是预期的行为,还是什么?
答案 0 :(得分:2)
EJB规范并未说明每次调用后无状态bean 丢弃其状态。它声明应用程序开发人员不能依赖bean 保持其状态。这是一个微妙但非常重要的区别。可以多次使用相同的bean实例;这并没有否定无国籍。
答案 1 :(得分:2)
重要的是每个计时器都有一个查找,你可能得到一个不同的豆实例,
但“可能”意味着您仍然可以获得相同的实例,因为它是从一个豆池中获得的
容器为您管理。
使用相同的计时器对象没有任何问题,
只要它提供适当的功能。
这意味着作为开发人员,您不能对bean的状态做出任何假设,以及是否将在新的bean查找时恢复它。
答案 2 :(得分:1)
无状态bean可以根据需要多次使用。它们不是每次都必须创建的。您可以在http://docs.oracle.com/javaee/6/tutorial/doc/giplj.html
查看EJB LifeCycle答案 3 :(得分:1)
这是预期的行为(根据Java EE规范),实际上比这复杂一点。
app服务器正在管理staless会话bean池,并使用此池中的实例来服务客户端请求。如果服务器上有一些负载,那么将从池中使用几个bean,每个bean都有自己的状态。因此,在您的测试中,您有时会打印出相同的字符串值,有时会打印另一个字符串值。
您不应该将属性用于业务逻辑。但是,出于技术目的使用属性(例如,保留对DB的引用)有时是个好主意。
答案 4 :(得分:1)
容器有一个无状态会话bean池。 它是容器内部处理活动实例的数量(据我所知) 对于您的情况,似乎计时器调用相同的实例。