繁体   English   中英

我应该在哪里放置@Transactional注释:在接口定义或实现类?

[英]Where should I put @Transactional annotation: at an interface definition or at an implementing class?

代码中标题的问题:

@Transactional (readonly = true)
public interface FooService {
   void doSmth ();
}


public class FooServiceImpl implements FooService {
   ...
}

VS

public interface FooService {
   void doSmth ();
}

@Transactional (readonly = true)
public class FooServiceImpl implements FooService {
   ...
}

来自http://static.springsource.org/spring/docs/2.0.x/reference/transaction.html

Spring团队的建议是,您只使用@Transactional注释来注释具体类,而不是注释接口。 您当然可以将@Transactional注释放在接口(或接口方法)上,但这只会在您使用基于接口的代理时按预期工作。 注释不是继承的这一事实意味着如果您使用基于类的代理,那么基于类的代理基础结构将无法识别事务设置,并且该对象将不会被包装在事务代理中(这将是非常糟糕的 ) 。 因此,请参考Spring团队的建议,并使用@Transactional注释仅注释具体类(以及具体类的方法)。

注意:由于此机制基于代理,因此只会拦截通过代理进入的“外部”方法调用。 这意味着'自调用',即目标对象中调用目标对象的其他方法的方法,即使被调用的方法用@Transactional标记,也不会在运行时导致实际的事务!

(重点加在第一句,其他重点来自原文。)

您可以将它们放在界面上,但要警告在某些情况下交易可能不会发生。 请参阅Spring文档的Secion 10.5.6中的第二个提示:

Spring建议您只使用@Transactional注释来注释具体类(以及具体类的方法),而不是注释接口。 您当然可以将@Transactional注释放在接口(或接口方法)上,但这只能在您使用基于接口的代理时按预期工作。 Java注释不是从接口继承的事实意味着如果您使用基于类的代理(proxy-target-class =“true”)或基于编织的方面(mode =“aspectj”),那么事务设置是代理和编织基础设施无法识别,并且该对象不会被包装在事务代理中,这将是非常糟糕的。

出于这个原因,我建议将它们放在实现上。

另外,对我来说,事务似乎是一个实现细节,因此它们应该在实现类中。 想象一下,拥有不需要事务性的日志记录或测试实现(模拟)的包装器实现。

Spring的建议是注释具体实现而不是接口。 在界面上使用注释并不正确,只能滥用该功能并无意中绕过@Transaction声明。

如果你在一个接口中标记了一些事务性的东西,然后在spring的其他地方引用它的一个实现类,那么spring创建的对象不会明显地遵循@Transactional注释。

在实践中,它看起来像这样:

public class MyClass implements MyInterface { 

    private int x;

    public void doSomethingNonTx() {}

    @Transactional
    public void toSomethingTx() {}

}

在具体类上支持@Transactional:

我更喜欢在3个部分中构建一个解决方案:API,实现和Web(如果需要)。 我尽量通过最小化依赖性将API保持为轻/简/ POJO。 如果您在分布式/集成环境中进行播放,尤其重要,您必须共享API。

放置@Transactional需要API部分中的Spring库,恕我直言是无效的。 所以我更喜欢在运行事务的实现中添加它。

把它放在接口上很好,因为IFC的所有可预见的实施者都关心TX数据(交易不是数据库处理的问题)。 如果该方法不关心TX(但你需要把它放在那里用于Hibernate或其他),请把它放在impl上。

另外,在接口中的方法上放置@Transactional可能会更好一些:

public interface FooService {
    @Transactional(readOnly = true)
    void doSmth();
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM