【问题标题】:Does this annotation work for Spring declarative transaction此注释是否适用于 Spring 声明性事务
【发布时间】:2012-05-13 08:21:36
【问题描述】:

据我所知,Spring 使用 JDK 为实现任何接口的类生成动态代理,而使用 Cglib 为不实现任何接口的类生成动态代理。对于描述性事务,Spring 使用代理来添加事务方面。请看下面的代码:

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" /> 

【问题讨论】:

    标签: spring proxy aop transactional


    【解决方案1】:

    JDK 动态代理

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

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

    但是,如果您从updateA() 调用updateB(),它是事务性的,因为它将绑定到由updateA() 启动的事务(使用默认事务传播)。

    CGLIB 代理

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

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

    【讨论】:

    • 谢谢你,托马斯。如果我有这个配置,Spring 会为我选择哪种情况:
    • @Jacky:默认情况下 Spring 使用 JDK 代理。如果设置了proxy-target-class 属性,它将升级到CGLIB 代理,请参阅:11.5.6 Using @Transactional
    猜你喜欢
    • 2016-09-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-10-01
    • 2019-01-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多