潍坊兆通网站建设,wordpress编辑器添加短代码按钮,家具展示网站源码,企业网站制作心得事务失效场景 方法用private或final修饰 Spring底层使用了AOP#xff0c;而AOP的实现方式有两种#xff0c;分别是JDK动态代理和CGLIB#xff0c;JDK动态代理是实现抽象接口#xff0c;CGLIB是继承父类,无论哪种方式#xff0c;都需要重写方法来进行方法增强#xff0c;而…事务失效场景 方法用private或final修饰 Spring底层使用了AOP而AOP的实现方式有两种分别是JDK动态代理和CGLIBJDK动态代理是实现抽象接口CGLIB是继承父类,无论哪种方式都需要重写方法来进行方法增强而用private或final修饰的方法都是不能被重写的 方法自调用(如何解决方法自调用导致的事务失效) UserService类中开启A方法调用B方法直接调用A方法会导致B方法的Transactional注解不生效从而导致事务失效
Component
public class UserService{Autowiredprivate JdbcTemplate jdbcTemplate;Transactionalpublic void A() {//this.B()和B()同理B();}Transactional(propagation Propagation.NEVER)public void B(){jdbcTemplate.execute(insert into user values(1, 1, 1));throw new NullPointerException();}
}为什么事务会失效Spring生成的代理类大致如下调用A方法会执行$Proxy0.A()而B方法是被代理对象target调用的所以方法不会被增强
public class $Proxy0 extends UserService {private UserService target;public void A() {//建立数据库连接ConnectionConnection connection DriverManager.getConnection(jdbc:mysql:///user);connection.setAutoCommit(false);try{target.A();}catch(RuntimeException exception){connection.rollback();return;}connection.commit();}
}多线程调用 执行SQL时会从ThreadLocal里获取数据库连接对象而ThreadLocal是线程隔离的新线程无法从主线程的ThreadLocal里获取数据库连接对象所以只能新建一个数据库连接来执行SQL此时autoCommit默认是true执行完SQL就会自动提交抛出异常也就不能回滚了
Component
public class UserService {Autowiredprivate JdbcTemplate jdbcTemplate;Transactionalpublic void B() {new Thread(() - {jdbcTemplate.execute(insert into user values(1, 1, 1));throw new NullPointerException();}).start();}
}类没有被Spring管理 数据库不支持事务 异常被手动try-catch掉了
如何解决方法自调用导致的事务失效 自己注入自己
Component
public class UserService {Autowiredprivate JdbcTemplate jdbcTemplate;Autowiredprivate UserService userService;public void A() {//从Spring容器中取出代理对象userService.B();}Transactionalpublic void B() {jdbcTemplate.execute(insert into user values(1, 1, 1));throw new NullPointerException();}
}把被调用的方法拆分到别的Bean中然后再把这个Bean注入进来 AopContext.currentProxy() EnableAspectJAutoProxy(exposeProxy true)
Component
public class UserService {Autowiredprivate JdbcTemplate jdbcTemplate;public void A() {UserService userService (UserService) AopContext.currentProxy();userService.B();}Transactionalpublic void B() {jdbcTemplate.execute(insert into user values(1, 1, 1));throw new NullPointerException();}
}