目前的情况:我有一些服务,有几个典型的服务方法,如create(),remove(),findXy(),...等。现在我想同时阻止两个不同的服务调用,这意味着我想要在第一次输入后锁定我的servicecall,所以第二个客户端(或同一个客户端)只会在第一个客户端完成后立即输入该方法。
出于锁定目的,我们通常使用ReentrantLocks。他们的工作非常好。但现在我怀疑如何实现这些ReentrantLocks,因为我不想在每个方法中插入它们。此外,我们的服务层已经自己定义了它们的事务上下文,这意味着,当我将它们集成到方法本身时,事务已经在锁定发生之前就已经开始了。
public class WorkerServiceServerImpl implements WorkerServiceRemote
{
private static final ReentrantLock workerLock = new ReentrantLock( true );
@Autowired
private WorkerDao workerDao;
@Override
@Transactional
public int createWorker( int projectId ) throws RemoteException
{
workerLock.lock();//NO GOOD! Transaction already started!
try
{
workerDao.create( projectId );
//Do some more stuff...
}
finally
{
workerLock.unlock();//Unlock, next request can be handled!
}
}
...
}
当然我可以在这个WorkerServiceImpl类之上创建一个ServiceLayer,只是将调用转发给原始服务,但是因为我有30个服务,我想知道,如果有任何全局解决方案来解决这个问题。或者是否可以创建一个在事务开始之前触发的自己的注释?
欢迎任何想法,提前感谢! ymene
编辑:为简单起见,我选择CRUD方法。当然,这些服务调用要先进得多,并且可以在一次调用中调用不同的CRUD方法。
答案 0 :(得分:2)
关于这种设计,有几点可以提出:
将锁应用于服务方法的需求看起来很奇怪。如果您在并发执行服务方法时遇到一些问题,那么在访问底层数据库时通过正确配置事务来解决它们可能会更好。
unlock()
块内调用 finally
。
如果您的服务是单身,则使用ReentrantLock
相当于标记您的方法synchronized
。
您可以创建方面以将同步应用于方法。请参阅7. Aspect Oriented Programming with Spring,尤其是7.2.4.7 Advice ordering。
答案 1 :(得分:1)
由于您似乎使用的是Spring,因此可以定义单例LockInterceptor,并在事务拦截器之前将其放入拦截器堆栈中。这个拦截器非常简单:
import org.aopalliance.intercept.*;
public class LockInterceptor implements MethodInterceptor {
@Override
public synchronized Object invoke(MethodInvocation mi) throws Throwable {
return mi.proceed();
}
}