据我所知,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" />
答案 0 :(得分:1)
在这种情况下,您的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: proxying和Spring AOP riddle。