Juh*_*älä 184 java spring annotations transactions
如果我在Spring bean中的私有方法上有@Transactional -annotation,那么注释是否有效?
如果@Transactional注释是在公共方法上,则它可以工作并打开事务.
public class Bean {
public void doStuff() {
doPrivateStuff();
}
@Transactional
private void doPrivateStuff() {
}
}
...
Bean bean = (Bean)appContext.getBean("bean");
bean.doStuff();
Run Code Online (Sandbox Code Playgroud)
ska*_*man 212
答案你的问题是否定的 - @Transactional如果用于注释私有方法将无效.代理生成器将忽略它们.
方法可见性和
@Transactional使用代理时,应仅将
@Transactional注释应用于具有公共可见性的方法.如果使用注释注释protected,private或package-visible方法,则@Transactional不会引发错误,但带注释的方法不会显示已配置的事务设置.如果需要注释非公共方法,请考虑使用AspectJ(见下文).
Ral*_*lph 149
该问题不是私人的或公开的,问题是:如何调用它以及您使用哪种AOP实现!
如果您使用(默认)Spring Proxy AOP,那么@Transational只有当呼叫通过代理时,才会考虑Spring提供的所有AOP功能(如).- 如果从另一个 bean 调用带注释的方法,通常就是这种情况.
这有两个含义:
@Transactional所以不考虑它们的注释.恕我直言,你应该使用aspectJ模式,而不是Spring代理,将克服这个问题.AspectJ Transactional Aspects甚至编织成私有方法(检查Spring 3.0).
Juh*_*älä 30
默认情况下,该@Transactional属性仅在从applicationContext获取的引用上调用带注释的方法时才起作用.
public class Bean {
public void doStuff() {
doTransactionStuff();
}
@Transactional
public void doTransactionStuff() {
}
}
Run Code Online (Sandbox Code Playgroud)
这将打开一个交易:
Bean bean = (Bean)appContext.getBean("bean");
bean.doTransactionStuff();
Run Code Online (Sandbox Code Playgroud)
这不会:
Bean bean = (Bean)appContext.getBean("bean");
bean.doStuff();
Run Code Online (Sandbox Code Playgroud)
注意:在代理模式(默认设置)下,只会拦截通过代理进入的"外部"方法调用.这意味着'自调用',即目标对象中调用目标对象的其他方法的方法,即使被调用的方法被标记,也不会在运行时导致实际的事务
@Transactional!如果您希望自我调用也包含在事务中,请考虑使用AspectJ模式(见下文).在这种情况下,首先不会有代理; 相反,目标类将被"编织"(即它的字节代码将被修改),以便
@Transactional在任何类型的方法上变成运行时行为.
Jam*_*ins 12
是的,可以在私有方法上使用@Transactional,但正如其他人所提到的,这不会开箱即用.您需要使用AspectJ.我花了一些时间来弄清楚如何使它工作.我将分享我的结果.
我选择使用编译时编织而不是加载时编织,因为我认为这是一个更好的选择.此外,我正在使用Java 8,因此您可能需要调整一些参数.
首先,添加aspectjrt的依赖项.
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.8.8</version>
</dependency>
Run Code Online (Sandbox Code Playgroud)
然后添加AspectJ插件来在Maven中进行实际的字节码编织(这可能不是一个最小的例子).
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>aspectj-maven-plugin</artifactId>
<version>1.8</version>
<configuration>
<complianceLevel>1.8</complianceLevel>
<source>1.8</source>
<target>1.8</target>
<aspectLibraries>
<aspectLibrary>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
</aspectLibrary>
</aspectLibraries>
</configuration>
<executions>
<execution>
<goals>
<goal>compile</goal>
</goals>
</execution>
</executions>
</plugin>
Run Code Online (Sandbox Code Playgroud)
最后将此添加到您的配置类
@EnableTransactionManagement(mode = AdviceMode.ASPECTJ)
Run Code Online (Sandbox Code Playgroud)
现在,您应该能够在私有方法上使用@Transactional.
这种方法的一个警告:您需要配置IDE以了解AspectJ,否则如果您通过Eclipse运行应用程序,例如它可能无法正常工作.确保您测试直接Maven构建作为完整性检查.
小智 5
Spring Docs 解释说
在代理模式下(默认),只有通过代理进入的外部方法调用才会被拦截。这意味着自调用实际上是目标对象中的一个方法调用目标对象的另一个方法,即使被调用的方法用@Transactional 标记,也不会在运行时导致实际事务。
如果您希望自调用也与事务一起包装,请考虑使用 AspectJ 模式(请参阅下表中的模式属性)。在这种情况下,首先不会有代理;相反,目标类将被编织(即,其字节码将被修改),以便将 @Transactional 转换为任何类型方法的运行时行为。
另一种方式是用户BeanSelfAware
如果您需要在事务内包装私有方法,并且不想使用Aspectj,则可以使用TransactionTemplate。
@Service
public class MyService {
@Autowired
private TransactionTemplate transactionTemplate;
private void process(){
transactionTemplate.execute(new TransactionCallbackWithoutResult() {
@Override
protected void doInTransactionWithoutResult(TransactionStatus status) {
processInTransaction();
}
});
}
private void processInTransaction(){
//...
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
96259 次 |
| 最近记录: |