代碼示例
UserService測試接口類 package cn.sw.study.web.service; /** * Created by shaowei on 2017/4/26. */ public interface UserService { void addInfo(); void addOne(); }
UserServiceImpl測試實現類 package cn.sw.study.web.service.impl; import cn.sw.study.web.dao.UserMapper; import cn.sw.study.web.model.User; import cn.sw.study.web.service.UserService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.util.Date; /** * 用戶業務類 * Created by shaowei on 2017/4/26. */ @Service("userService") public class UserServiceImpl implements UserService{ @Autowired UserMapper userMapper; public void addInfo() { addOne(); } @Transactional public void addOne() { User record = new User(); record.setLoginName("tom"); record.setPwd("111111"); record.setMobile("13913913913"); record.setUsable(1); record.setCreateTime(new Date()); userMapper.insertSelective(record); int i = 1/0; // 測試事物的回滾 } }
現象描述
addInfo方法上沒有事務注解,addOne方法上有事務注解,此時運行addInfo調用addOne方法,不會產生事務,測試數據遇到異常沒有回滾。如果從外部類直接調用addOne方法,則事務是可以正常生效的。
解決方案
使用AopContext.currentProxy()來獲取代理類再調用,如下
UserServiceImpl測試實現類 package cn.sw.study.web.service.impl; import cn.sw.study.web.dao.UserMapper; import cn.sw.study.web.model.User; import cn.sw.study.web.service.UserService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.util.Date; /** * 用戶業務類 * Created by shaowei on 2017/4/26. */ @Service("userService") public class UserServiceImpl implements UserService{ @Autowired UserMapper userMapper; public void addInfo() { ((UserService)AopContext.currentProxy()).addOne(); } @Transactional public void addOne() { User record = new User(); record.setLoginName("tom"); record.setPwd("111111"); record.setMobile("13913913913"); record.setUsable(1); record.setCreateTime(new Date()); userMapper.insertSelective(record); int i = 1/0; // 測試事物的回滾 } }
新問題
再次運行,如果沒有添加expose-proxy="true"這個屬性(暴露代理對象),則會報錯
java.lang.IllegalStateException: Cannot find current proxy: Set 'exposeProxy' property on Advised to 'true' to make it available.
新問題解決:springboot中如何配置aop動態代理模式(轉載自:http://tingcream.com/blogArticle/detail/fd08e233b37844bca556ee393e46a928)
第一種方式:
在application.yml中有以下配置
spring:
aop:
#auto: true #默認為true,可省略
proxy-target-class: true # 默認為false即JDK動態代理,我們一般要設為true,使用CGLIB代理
這種方式只能將代理模式修改為了CGLIG,但是不能設置暴露cglib代理的目標對象。
第二種方式:
在springboot啟動類上標記這個注解
@EnableAspectJAutoProxy(exposeProxy=true,proxyTargetClass=true)
同時,排除 AopAutoConfiguration.class的自動化配置
很好,這種方式同時設置exposeProxy為true和proxyTargetClass為true,即強制采用cglib代理,和暴露cglib代理的目標對象。
第三種方式:
在springboot啟動類上引入spring.xml配置文件
@ImportResource({"classpath:/spring.xml"})
同時,排除 AopAutoConfiguration.class的自動化配置
在spring.xml 配置文件中配置
<!--1 aspectj 切面的支持 ,強制使用cglib,並暴露cglib代理的目標對象-->
<aop:aspectj-autoproxy proxy-target-class="true" expose-proxy="true"/>
<context:annotation-config />
