温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

spring service层调用同类中的方法是什么

发布时间:2021-11-11 09:51:33 来源:亿速云 阅读:227 作者:柒染 栏目:编程语言

spring service层调用同类中的方法是什么,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。

有这样的一道面试题:在service层调用别的service层的方法,他们的事务能否生效;如果是在同一个类中调用带有@Transactional注解的方法,此时,他们的事务能否生效?
看了许多大神的blog,今天来做一下总结:

先给出大家答案:

  • 不同类之间的方法调用,如类A的方法a()调用类B的方法b(),这种情况事务是正常起作用的。只要方法a()或b()配置了事务,运行中就会开启事务,产生代理(注意是不同的类,如果是类A方法a()调用类A方法b(),那么只有a()配置了事务才会有效)。

  • 同一类内方法调用,无论被调用的b()方法是否配置了事务,此事务在被调用时都将不生效。


(1) 首先先说一下Spring事务管理详解:下面的这篇博客介绍的很清楚了,从基本原理、事务的特性、隔离级别以及事务实现的三种方式

Spring事务管理详解

https://blog.csdn.net/donggua3694857/article/details/69858827

(2) 知道了事务的一些知识后,下面说一下@Transactional注解的信息(大家着重看一下4 5 6条的解释)

1.在需要事务管理的地方加@Transactional 注解。@Transactional 注解可以被应用于接口定义和接口方法、
类定义和类的 public 方法上。

2.@Transactional 注解只能应用到 public 可见度的方法上。 如果你在 protected、private 或者
 package-visible 的方法上使用 @Transactional 注解,它也不会报错, 但是这个被注解的方法将不会展示
已配置的事务设置。

3.注意仅仅 @Transactional 注解的出现不足于开启事务行为,它仅仅 是一种元数据。
  必须在配置文件中使用配置元素,才真正开启了事务行为。(spring配置文件中,开启声明式事务)
  例如可以这么配置:
  <!--======= 事务配置 Begin ================= -->
	<!-- 事务管理器(由Spring管理MyBatis的事务) -->
	<bean id="transactionManager"
		class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
		<!-- 关联数据源 -->
		<property name="dataSource" ref="dataSource"></property>
	</bean>
	<tx:annotation-driven transaction-manager="transactionManager"
		proxy-target-class="true" />
  <!--======= 事务配置 End =================== -->

4.通过 元素的 “proxy-target-class” 属性值来控制是基于接口的还是基于类的代理被创建。
如果 “proxy-target-class” 属值被设置为 “true”,那么基于类的代理将起作用(这时需要CGLIB库
cglib.jar在CLASSPATH中)。如果 “proxy-target-class” 属值被设置为 “false” 或者这个属性被省略,
那么标准的JDK基于接口的代理将起作用。

5.Spring团队建议在具体的类(或类的方法)上使用 @Transactional 注解,而不要使用在类所要实现的任何接口
上。在接口上使用 @Transactional 注解,只能当你设置了基于接口的代理时它才生效。因为注解是 不能继承 
的,这就意味着如果正在使用基于类的代理时,那么事务的设置将不能被基于类的代理所识别,而且对象也将不会被事
务代理所包装。

6.@Transactional的事务开启 ,或者是基于接口的 或者是基于类的代理被创建。所以在同一个类中一个无事务的方法
用另一个有事务的方法,事务是不会起作用的。如果在有事务的方法中调用另外一个有事务的方法,那么事务会起作用,
并且共用事务。如果在有事务的方法中调用另外一个没有事务的方法,那么事务也会起作用。


不生效的原因:
       当从类外调用没有添加事务的方法a()时,从spring容器获取到的serviceImpl对象实际是包装好的proxy对象,因此调用a()方法的对象是动态代理对象。而在类内部a()调用b()的过程中,实质执行的代码是this.b(),此处this对象是实际的serviceImpl对象而不是本该生成的代理对象,因此直接调用了b()方法。

解决办法:
 

1. 放到不同的类中进行调用
2. 在spring配置文件中加入配置
   <aop:aspectj-autoproxy/>
   <aop:aspectj-autoproxy proxy-target-class=“true” expose-proxy=“true” />
3. 将之前使用普通调用的方法,换成使用代理调用
   ((TestService)AopContext.currentProxy()).testTransactional2();
   获取到TestService的代理类,再调用事务方法,强行经过代理类,激活事务切面。
4. 使用异步操作,另外开启一个线程或者将这个消息写入到队列里面,在其他的地方进行处理

关于spring service层调用同类中的方法是什么问题的解答就分享到这里了,希望以上内容可以对大家有一定的帮助,如果你还有很多疑惑没有解开,可以关注亿速云行业资讯频道了解更多相关知识。

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI