【发布时间】:2017-06-02 09:37:43
【问题描述】:
我的问题与Pass object between before and after advice? 中的问题相同,但是接受的答案在我的情况下不起作用,我想要求对此主题进行一些澄清。
实际上,我正在使用around 建议,但我必须更改它。让我们考虑一个例子:
public Object registerLog( ProceedingJoinPoint jpoint)
{
SomeObject so = getSomeData( jpoint.getArgs());
Object result = jpoint.proceed();
getMoreData( result, so);
log( so);
}
我的proceed() 方法是将对象插入数据库。在这种情况下,我在事务提交之前记录INSERT 的结果,这不是很好。这就是为什么我想将around 建议拆分为before 和after,所以当记录已经在数据库中时,我可以登录after。但是,在将对象存储到数据库之前,我仍然需要获取对象的一些数据。
当然,解决方案必须是线程安全的,所以我不能只在我的方面类中添加一个SomeObject 成员。从链接的问题中,我了解到ThreadLocal,到目前为止,这是我找到的最佳解决方案。但是,我以前从未使用过它,我想问一下是否有其他解决方案。也许有一种方法可以在处理方面时强制事务提交(我现在不确定这是否是个好主意)?
更新详情
我有两个切入点:
<aop:pointcut id="mngrPointcut" expression="execution(* com.mngr.Foo.*(..))"/>
<aop:pointcut id="savePointcut" expression="execution(* com.mngr.Foo.save(..))"/>
第一个切入点有建议
<aop:advisor advice-ref="txAdvice" pointcut-ref="mngrPointcut"/>
建议在哪里
<tx:advice id="txAdvice" transaction-manager="txManager">
<tx:attributes>
<tx:method name="select*,search*,get*" propagation="REQUIRED" rollback-for="Exception" read-only="true"/>
<tx:method name="*" propagation="REQUIRED" rollback-for="Exception"/>
</tx:attributes>
</tx:advice>
对于第二个切入点,我有方面
<aop:aspect ref="logAspect">
<aop:around method="registerLog" pointcut-ref="savePointcut"/>
</aop:aspect>
当调用com.mngr.Foo.save() 时,两个切入点都有效。可能是因为申报顺序,先触发mngrPointcut,开始新的交易。然后savePointcut 被触发,开始一个切面。正如我上面提到的,方面负责记录。由于触发切入点的顺序,对象在存储到数据库之前被记录,这是错误的。我认为我必须使用before 和after 通知而不是around,所以当事务已经提交时,我可以在after 部分调用log() 方法。
【问题讨论】:
-
你需要遵守周围的建议,只要确保你的方面在 spring 的事务方面之前执行。如果您使用 aspectj,“声明优先级”就是您要查找的内容。
-
为什么
around不适用于您的情况?拆分为before和after可以得到什么?请详细说明,最好是一些示例代码。 -
@NándorElődFekete 谢谢。设置交易和建议的顺序解决了这个问题。考虑将其发布为答案。
-
@kriegaex 我想控制事务提交的时刻,并使用
after建议当业务对象已经在数据库中时必须执行的方法。请检查更新以获取一些详细信息。
标签: java spring aop aspectj spring-aop