@Transactional 注解应该放在哪里:接口定义还是实现类?

问题描述 投票:0回答:5

代码中标题的问题:

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


public class FooServiceImpl implements FooService {
   ...
}

public interface FooService {
   void doSmth ();
}

@Transactional (readonly = true)
public class FooServiceImpl implements FooService {
   ...
}
java spring annotations coding-style
5个回答
143
投票

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

Spring 团队的建议是只使用

@Transactional
注解来注解具体类,而不是注解接口。 你当然可以将
@Transactional
注解放在接口(或接口方法)上,但这只会如果您使用基于接口的代理,它会按照您期望的方式工作。注释“不是继承的”这一事实意味着,如果您使用基于类的代理,那么基于类的代理基础设施将无法识别事务设置,并且对象将不会被包装在事务代理中(这显然是)。因此,请务必采纳 Spring 团队的建议,仅使用 @Transactional 注释来注释具体类(以及具体类的方法)。

注意:由于此机制基于代理,因此只有通过代理传入的“外部”方法调用才会被拦截。

这意味着“自调用”,即目标对象中的方法调用对象的其他方法目标对象,即使调用的方法标有 @Transactional

,也不会在运行时导致实际事务

(强调添加到第一句,其他强调来自原文。)


12
投票
建议

是注释具体的实现而不是接口。在接口上使用注释并不是不正确,只是有可能滥用该功能并无意中绕过您的 @Transaction 声明。 如果您在接口中标记了某些事务性内容,然后在 spring 中的其他地方引用其实现类之一,则 spring 创建的对象不会遵守 @Transactional 注释,这一点并不十分明显。

实际上,它看起来像这样:

public class MyClass implements MyInterface { private int x; public void doSomethingNonTx() {} @Transactional public void toSomethingTx() {} }




1
投票

放置 @Transactional 需要 API 部分中的 Spring 库,恕我直言,这并不有效。所以我更喜欢将其添加到运行事务的实现中。

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


0
投票
@Transactional

放在界面中的方法上可能会更好一点:

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

    

© www.soinside.com 2019 - 2024. All rights reserved.