我在glassfish中部署了一个war文件。我们有一个单例bean,其中有一个同步方法。
@TransactionAttribute (TransactionAttributeType.REQUIRED)
public synchronized void do()
{
...
}
然而,我注意到事务是在调用方法之前启动的。在调用者获得bean类监视器上的锁之后,如何启动事务?
谢谢。
更新:我们只是想有一个bean方法,一次只能由一个线程调用。在前一个线程完全完成之前,我们不希望任何其他线程调用该方法。我创建了另一个线程,在那里我得到了使用单例bean的想法:无状态会话bean中的同步方法在glassfish
中不像预期的那样工作更新:在做了一些阅读之后,似乎我可以创建我自己的事务UserTransaction。会得到支持吗?不要紧。我得到了这个错误信息:
Only session beans with bean-managed transactions can obtain UserTransaction
我认为一种方法是通过将对方法的调用包装在另一个bean (YourBean将是您的bean类的接口)中来将同步移出bean:
public class WrapperBeanImpl implements WrapperBean {
private YourBean yb;
private final Object lock;
@Resource
private SessionContext ctx;
@PostConstruct
public void init() {
yb = ctx.getBusinessObject(YourBean.class);
}
@TransactionAttribute(TransactionAttributeType.NEVER)
public void synchronizedDo() {
synchronized(lock) {
yb.do();
}
}
}
(从http://www.javahelp.info/2009/11/01/using-transactionattribute-in-submethods-on-same-ejb3-beans/略微修改的示例)
当然,这并不能真正阻止任何人直接调用do()方法,绕过这个额外的同步,尽管这可能不是问题。您还可以选择在bean中保留同步,作为额外的保护措施。
只要在类级别上使用@ConcurrencyManagementType(CONTAINER)
,容器将保持同步。并且使用没有synchronized
指令的方法