在使用@Transactional注解的方法内部使用synchronized,在方法执行完毕后锁就会被释放,而此时事务可能还没有被提交,此时若有其他线程对数据进行修改会出现并发安全问题。

若将锁加在函数调用的地方,将整个方法进行加锁。这样当方法执行完毕且事务也提交完毕之后锁才会被释放。

public int A(){
  synchronized(){
    return B();
  }
}

@Transactional
public int B(){
  return 1;
}

代码如上所示,因为在添加注解后Spring生成了动态代理对象,用生成的代理对象做事务处理,而这种调用方式调用的是原始对象,会导致事务失效。

解决方式

使用AopContext.currentProxy()方法获取当前对象的代理对象

  1. 引入依赖
<dependency>
  <groupId>org.aspectj</groupId>
  <artifactId>aspectjweaver</artifactId>
  <version>1.9.19</version>
</dependency>
  1. 启动类添加注解

@EnableAspectJAutoProxy(exposeProxy = true)暴露代理对象

  1. 获取对象
public class Test(){
  
  public int b(){
    synchronized(){
      //返回对象为Object,强制转换为相应的对像,注意类为Test,B只是Test类中的一个方法
      Test proxy = (Test)AopContect.currentProxy();
      return proxy.b();
    }
  }

  @Transactional
  public int b(){
    return 1;
  }
  
}