在建议之前和之后传递对象

时间:2017-06-02 09:37:43

标签: java spring aop aspectj spring-aop

我的问题与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建议拆分为beforeafter,因此当记录已经在数据库中时,我可以登录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,开始一个方面。如上所述,方面负责记录。由于触发切入点的顺序,对象在存储到数据库之前会被记录,这是错误的。我认为我必须使用beforeafter建议而不是around,因此我可以在log()部分调用after方法,当事务已经comitted。

2 个答案:

答案 0 :(得分:1)

感谢NándorElődFekete的评论,我通过设定交易顺序和建议来解决问题。低阶强制方面在前进的路上和在出路上反向运行。没有订购的方面在订单之后运行。

答案 1 :(得分:0)

如果您遇到方面优先级问题,将切入点类型从around更改为after将无济于事。相反,您希望使方面实现Ordered界面,或者@Ordertype PostContainer = VideoContainer Video | PodcastContainer Podcast 注释,两者都如Spring AOP manual中所述。还请在章节中进一步搜索“订购”这一术语(没有双关语),以查看一些示例代码。