Spring 文档建议不要将@Transactional 注解放在接口(interface)方法上,因为接口(interface)注解不会被类继承。但是,使用 Java 8,我们可以在接口(interface)中提供具体的默认实现。如果这样一个默认的接口(interface)方法需要作为事务边界,我们别无选择:必须在接口(interface)方法上加上@Transactional注解。
这会起作用吗(即在这种情况下,spring 会尊重事务边界)吗?如果是这样,这种方法是否有任何隐藏的陷阱?
最佳答案
在为使用 @Transactional
注释的类或包含使用 @Transactional
注释的方法生成代理 bean 时,Spring 使用(以及其他)BeanFactoryTransactionAttributeSourceAdvisor
作为 Advisor
>.
当需要代理它时,它使用 bean 的类类型(使用 CGLIB)来生成代理。所以我们想看看用 @Transactional
注释的 default
方法是否从实现类的角度可见。
这是一个 Java 8 SSCCE
public static void main(String[] args) throws Exception{
Class<?> randomImplClass = RandomImpl.class;
System.out.println(randomImplClass);
Easy annotation = randomImplClass.getAnnotation(Easy.class);
System.out.println("Class: " + randomImplClass);
System.out.println("Class Annotation: " + annotation);
Method method = randomImplClass.getMethod("doRandom");
annotation = method.getAnnotation(Easy.class);
System.out.println("Method: " + method);
System.out.println("Method Annotation: " + annotation);
}
public static class RandomImpl implements Random{}
@Easy
interface Random {
@Easy
default void doRandom() {System.out.println("testing");};
}
@Target(value = {METHOD, TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface Easy {}
打印出来的
class TestEnhancer$RandomImpl
Class: class TestEnhancer$RandomImpl
Class Annotation: null
Method: public default void TestEnhancer$Random.doRandom()
Method Annotation: @TestEnhancer$Easy()
表示该注解是为接口(interface)的方法继承的。因此,当类没有覆盖 default
方法时,Spring 似乎能够添加 @Transactional
行为。如果它已覆盖它,则注释不会被继承。
关于java - 在 Java 8 默认接口(interface)方法上使用 Spring @Transactional 注释是否安全?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20460957/