这个注释是否适用于Spring声明式事务

时间:2012-05-13 08:21:37

标签: spring proxy aop transactional

据我所知,Spring使用JDK为实现任何界面的类生成动态代理,同时使用Cglib为不实现任何界面的类生成动态代理。对于decarative transcation,Spring使用proxy来添加事务方面。请看下面的代码:

interface Demo {
    void methodA();
}
public class DemoImpl implements Demo{
    @Transactional
    public void updateA() {}
    @Transactional
    public void updateB() {}
}

我认为updateA可以很好地处理事务。但是updateB方法怎么样? @Transactional是否适合它? 也许我的理解不正确。如果提供相关的Spring源代码来解释Spring如何使用JDK / cglib来代理类和接口,那就太棒了。感谢

我在xml中有配置:

<tx:annotation-driven transaction-manager="transactionManager" /> 

1 个答案:

答案 0 :(得分:1)

JDK动态代理

在这种情况下,您的bean使用实现Demo接口的代理进行包装。从那一刻起,您只能使用该界面。尝试注入或获取DemoImpl类型的bean会导致可怕的Abstract DAO pattern and Spring's "Proxy cannot be cast to ..." problem!

这样可以回答您的问题 - 您只能访问updateA(),这是唯一的交易方法。 updateB()周围的注释将被忽略。

但是,如果您从updateB()致电updateA(),那么 将是事务性的,因为它将绑定到updateA()启动的事务(默认事务传播)。

CGLIB代理

在这种情况下,接口将被忽略。 将创建DemoImpl的子类(显然也实现Demo接口)并在两个update*()方法上应用事务行为。现在,如果你注入DemoImpl类型的bean(在这种情况下根本不需要接口,并且Impl后缀很难看),你可以安全地和事务性地调用这两种方法。

有关更多详情,请参阅我的文章:Spring pitfalls: proxyingSpring AOP riddle