在通知前后传递对象
Pass object between before and after advice
我的问题与 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
。但是,在将对象存储到数据库之前,我仍然需要获取对象的一些数据。
当然,解决方案必须是线程安全的,所以我不能只向我的方面 class 添加一个 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()
方法,当交易已经完成时犯了。
如果您在方面优先级方面遇到问题,将切入点类型从 around
更改为 after
将无济于事。相反,您希望让方面实现 Ordered
接口或通过 @Order
对它们进行注解,两者均如 Spring AOP manual 中所述。还请在本章的下方搜索术语 "ordered",以便(没有双关语意)查看一些示例代码。
感谢 Nándor Előd Fekete 的评论,我通过设置交易顺序和建议解决了这个问题。较低阶的力方面 运行 较早进入和退出时相反。未排序的方面 运行 在有顺序的方面之后。
我的问题与 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
。但是,在将对象存储到数据库之前,我仍然需要获取对象的一些数据。
当然,解决方案必须是线程安全的,所以我不能只向我的方面 class 添加一个 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()
方法,当交易已经完成时犯了。
如果您在方面优先级方面遇到问题,将切入点类型从 around
更改为 after
将无济于事。相反,您希望让方面实现 Ordered
接口或通过 @Order
对它们进行注解,两者均如 Spring AOP manual 中所述。还请在本章的下方搜索术语 "ordered",以便(没有双关语意)查看一些示例代码。
感谢 Nándor Előd Fekete 的评论,我通过设置交易顺序和建议解决了这个问题。较低阶的力方面 运行 较早进入和退出时相反。未排序的方面 运行 在有顺序的方面之后。