有关于 spring 注解“继承”的“重复”问题,答案很坚决,但可能不正确:否。
当然,当我们重写方法时,注释不会被继承。但仅仅
的存在org.springframework.core.annotation.AnnotationUtils#findAnnotation
遵循方法重写引出了一个问题:是否(以及如何)@Transactional 注释“继承”。我还可以找到:
org.springframework.core.annotation.MergedAnnotations.SearchStrategy
其中 TYPE_HIERARCHY 枚举特别表明 spring “继承”它们。
问题:
@交易 公共无效a(){}
@Overrides
public void a() {}
如果我调用a(),是否会打开交易?让我们假设,代理已正确创建,方法是公共的,等等。其他一切都很好。
的Javadoc:
当此注释在类级别声明时,它将作为默认值应用于声明类及其子类的所有方法。请注意,它不适用于类层次结构中的祖先类; 继承的方法需要在本地重新声明才能参与子类级别的注释。有关方法可见性约束的详细信息,请参阅参考手册的事务管理部分。 所以,如果你有
@Transactional
public class YourSuperClass {}
@Component
public class YourSubClass {
public void someMethod(){
//whatever
}
}
那么
someMethod
在逻辑上就是@Transactional
(从Spring的角度来看)。如果
someMethod
被覆盖,这也适用。
但是,情况不同
public class YourSuperClass {
@Transactional
public void someMethod(){
}
}
@Component
public class YourSubClass extends YourSuperClass {
@Override
public void someMethod(){
//whatever
}
}
在这种情况下,
someMethod
将不会是事务性的,除非您明确注释覆盖的版本。
所以,对于你的问题:
那么在父类方法和子类方法中,如果我调用a(),是否会打开事务?让我们假设,代理已正确创建,方法是公共的,等等。其他一切都很好。
- 不。如前所述,重写的方法不会是事务性的。但是,您可以通过围绕该方法创建一个包装器来解决这个问题:
public class YourSuperClass {
@Transactional
public final void yourMethod(){
yourMethodImpl();
}
protected void yourMethodImpl(){
//whatever
}
}
@Component
public class YourSubClass extends YourSuperClass{
@Override
protected void yourMethodImpl(){
//whatever
}
}
那么如果调用
yourMethodImpl
,yourMethod
将在事务中执行。考虑到显然有多种策略,是否有一些文档/最佳实践如何配置此行为。
- 如前所述,您可以检查
@Transactional
的 Javadoc,其中提到它是在类级别继承的,但在重写方法时则不是。我不知道还有什么其他策略。
有谁知道这些规则记录在哪里,我想知道如果父级是接口或抽象方法等会发生什么,并且执行扫描的代码并不那么容易,不能确定我没有忽略某些东西。
- 这些事情应该做同样的事情,但如果你想确定的话,我建议你自己尝试一下。