在Java8默认接口方法上使用Spring@Transactional注释安全吗?
Spring文档建议不要将@Transactional注释放在接口方法上,因为接口注释不是由类继承的。然而,使用Java8,我们可以在接口中提供一个具体的默认实现。如果这样一个默认接口方法需要作为事务边界,那么我们别无选择:我们必须在接口方法上添加@transactional注释 这是否有效(即,在这种情况下,spring是否尊重事务边界)?如果是这样,这种方法是否有任何隐藏的缺陷?Spring使用在Java8默认接口方法上使用Spring@Transactional注释安全吗?,java,spring,transactions,annotations,java-8,Java,Spring,Transactions,Annotations,Java 8,Spring文档建议不要将@Transactional注释放在接口方法上,因为接口注释不是由类继承的。然而,使用Java8,我们可以在接口中提供一个具体的默认实现。如果这样一个默认接口方法需要作为事务边界,那么我们别无选择:我们必须在接口方法上添加@transactional注释 这是否有效(即,在这种情况下,spring是否尊重事务边界)?如果是这样,这种方法是否有任何隐藏的缺陷?Spring使用BeanFactoryTransactionattributeSourceVisor作为顾问,为使
BeanFactoryTransactionattributeSourceVisor
作为顾问,为使用@Transactional
注释的类或包含@Transactional
注释的方法的类生成代理bean
当需要代理它时,它使用bean的类类型(带有CGLIB)来生成代理。因此,我们想看看从实现类的角度来看,用@Transactional
注释的default
方法是否可见
这是一个Java8SSCCE
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 {}
指示为接口的方法继承了注释。因此,当类没有重写默认方法时,Spring似乎能够添加@Transactional
行为。如果它覆盖了它,那么注释就不会被继承。如果您需要方法的默认实现,为什么不创建一个抽象类而不是接口呢?Java 8 API文档让我相信,接口默认方法的主要目的是允许在不破坏接口的旧实现的情况下向接口添加新方法。接口默认方法允许您创建,这是一种比传统Java接口更强大的编程构造。在带有事务的服务接口中使用mixin是否有正当理由是另一个问题,但这并不是不可想象的。使用抽象类也可以,但会将您限制为线性对象层次。混音器更灵活。非常好的测试。为了更进一步,您可以覆盖RandomImpl中的默认实现,并演示必须将注释放在覆盖方法上才能看到它。我认为这与使用继承没有任何区别。@JMB对,我是在本地做的,但没有在这里发布示例。最后一句话涵盖了它。我回家后再加上。
class TestEnhancer$RandomImpl
Class: class TestEnhancer$RandomImpl
Class Annotation: null
Method: public default void TestEnhancer$Random.doRandom()
Method Annotation: @TestEnhancer$Easy()