解決@Transactional事務在類內部方法調用不生效


代碼示例


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 />  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM