我正在编写一个Spring方面,以拦截用@Transactional
注释的方法来复制Liferay的行为。
因此,在我看来,代码如下:
@Aspect
class TransactionAspect extends TransactionSynchronizationAdapter
{
private final Logger logger = LoggerFactory.getLogger(TransactionAspect.class);
@Pointcut("within(@org.springframework.transaction.annotation.Transactional *)")
public void beanAnnotatedWithTransactional() {}
@Pointcut("execution(public * *(..))")
public void publicMethod() {}
@Pointcut("within(foo.bar.services..*)")
public void beanInsidePackage(){}
@Before("publicMethod() && beanAnnotatedWithTransactional() && beanInsidePackage()")
public void publicMethodInsideAClassMarkedWithTransactional()
{
if ( TransactionAspectSupport.currentTransactionStatus().isNewTransaction() )
{
TransactionSynchronizationManager.registerSynchronization(this);
TransactionalPortalCacheHelper.begin();
}
}
@Override
public void afterCompletion(int status)
{
switch (status)
{
case STATUS_COMMITTED :
TransactionalPortalCacheHelper.commit();
logger.info( "Commit!" ); break;
case STATUS_ROLLED_BACK :
TransactionalPortalCacheHelper.rollback();
logger.info( "Rollback!" ); break;
case STATUS_UNKNOWN :
logger.info( "Upps!" ); break; //TODO throw runtime exception?
}
}
}
使用此代码,方法将按预期截获。但是,调用实体的getCount,添加一个元素,再次计数的结果是不正确的。
如果我们看到Liferay的代码,这是正常的:
try {
session = openSession();
BatchSessionUtil.update(session, foo, merge);
foo.setNew(false);
} catch (Exception e) {
throw processException(e);
} finally {
closeSession(session);
}
finderCache.clearCache(FINDER_CLASS_NAME_LIST_WITH_PAGINATION);
这是在提交后清除缓存,但最后,对clearCache的调用到达: @覆盖 public void removeAll(){
if (_log.isTraceEnabled()) {
_log.trace(getAbbreviatedCacheName() + " DEL ALL");
}
if (TransactionalPortalCacheHelper.isEnabled()) {
TransactionalPortalCacheHelper.removeAll(_portalCache);
}
else {
_portalCache.removeAll();
}
}
并TransactionalPortalCacheHelper
对该电话说什么?
protected static void removeAll(PortalCache portalCache) {
Map<PortalCache, Map<Serializable, Object>> portalCacheMap =
_peekPortalCacheMap();
Map<Serializable, Object> uncommittedMap = portalCacheMap.get(
portalCache);
if (uncommittedMap != null) {
uncommittedMap.clear();
}
}
这里的问题是,portalCache上的数据会发生什么?不清除!因为TransactionalPortalCacheHelper已启用。
但是,问题是:如果我使用Liferay方法拦截器测试此行为,它按预期工作,我总是正确的结果。但是,如果我使用已经编码的方面,则会出现所描述的问题。那么,Liferay的真实流程是什么,添加并计算了元素,并将portalCaches的状态包含在FinderCache中?