[英]Is it safe to use a Spring @Transactional annotation on a Java 8 default interface method?
The Spring documentation recommends against putting @Transactional annotations on interface methods because interface annotations are not inherited by classes. Spring文档建议不要在接口方法上放置@Transactional注释,因为接口注释不是由类继承的。 However, with Java 8 we can provide a concrete default implementation in the interface. 但是,使用Java 8,我们可以在界面中提供具体的默认实现。 If such a default interface method needs to be the transactional boundary, we have no other choice: we have to put the @Transactional annotation on the interface method. 如果这样的默认接口方法需要是事务边界,我们别无选择:我们必须在接口方法上放置@Transactional注释。
Will this work (ie will spring respect the transaction boundary in this case)? 这会起作用(即在这种情况下春天是否会尊重交易边界)? If so, are there any hidden pitfalls to this approach? 如果是这样,这种方法有任何隐藏的陷阱吗?
Spring uses (among others) a BeanFactoryTransactionAttributeSourceAdvisor
as an Advisor
when generating a proxy bean for classes annotated with or containing methods annotated with @Transactional
. 在为使用@Transactional
注释的方法注释或包含注释的类生成代理bean时,Spring使用(以及其他) BeanFactoryTransactionAttributeSourceAdvisor
作为Advisor
。
When the time comes to proxy it, it uses the bean's class type (with CGLIB) to generate the proxy. 当需要代理它时,它使用bean的类类型(使用CGLIB)来生成代理。 So we want to see if the default
method annotated with @Transactional
will be visible from the implementing class' point of view. 因此,我们希望看看从实现类的角度来看,使用@Transactional
注释的default
方法是否可见。
Here's a Java 8 SSCCE 这是一个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 {}
which prints 打印
class TestEnhancer$RandomImpl
Class: class TestEnhancer$RandomImpl
Class Annotation: null
Method: public default void TestEnhancer$Random.doRandom()
Method Annotation: @TestEnhancer$Easy()
Indicating that the annotation was inherited for the interface's method. 指示为接口的方法继承了注释。 It seems, therefore, that Spring will be able to add @Transactional
behavior when the class has not overriden the default
method. 因此,当类没有覆盖default
方法时,Spring似乎能够添加@Transactional
行为。 If it has overriden it, then annotations are not inherited. 如果它已覆盖它,则不会继承注释。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.