• @Transactional spring 事务(转载)


     

    原文链接: http://www.cnblogs.com/sweetchildomine/p/6978037.html?utm_source=itdadao&utm_medium=referral

    补充推荐:https://stackoverflow.com/questions/4396284/does-spring-transactional-attribute-work-on-a-private-method

         http://blog.csdn.net/gudejundd/article/details/54380141

    对于像我这种喜欢滥用AOP的程序员,遇到坑也是习惯了,不仅仅是事务,其实只要脱离了Spring容器管理的所有对象,对于SpringAOP的注解都会失效,因为他们不是Spring容器的代理类,SpringAOP,就切入不了

    当然可以使用原生ASPECTJ,不用SpringAOP,但是基于生态链问题,还是尽量使用SpringAOP

    这里简单说一下,Spring如何选择使用CGLIB,或者是JDK代理,

    Spring 代理对象,cglib,jdk的问题思考,AOP 配置注解拦截 的一些问题.为什么不要注解在接口,以及抽象方法.

    简单来说,如果实现了某个接口,那么Spring就选择JDK代理(不一定),如果没有,那么就选择CGLIB代理,说起来简单,Spring还会闹脾气,不代理呢

    点击:根据Spring代理对象获得真实对象

    一直以来比较多的情况是在Controller 调用Service 的方法,把事务直接在Service的方法上,妥妥的没问题,事务正常执行

    考虑以下问题: 同对象的方法B 调用自己的方法A,这里的事务将会失效(严格上来说,只要对方法A使用注解AOP均会失效),原因是因为这里的this.调用的并不是Spring的代理对象

    复制代码
        
    @Service
    public class ClassA{ @Transactional(propagation = Propagation.REQUIRES_NEW) public void methodA(){ } /** * 这里调用methodA() 的事务将会失效 */ public void methodB(){ this.methodA(); } }
    复制代码

     最简单的解决方法为:(代理模式为JDK 的情况下(根据接口代理))

    复制代码
     @Service
        public class ClassA extends BaseClass{
    
            @Transactional(propagation = Propagation.REQUIRES_NEW)
        @Override public void methodA(){ } /** * 这里调用methodA() 的事务将会失效 */
         public void methodB(){         //使用getBean     ((BaseClass)SpringUtil.getBean("classA")).methodA(); } }
    复制代码

     第二种方式:

    解决第一步: 必须

    SpringBoot:注解开启cglib代理,开启 exposeProxy = true,暴露代理对象 (否则AopContext.currentProxy()) 会抛出异常

    复制代码
    @EnableAspectJAutoProxy(exposeProxy = true)
    public class Application{
        public static void main(String[] args) {
            SpringApplication.run(Application.class, args);
        }
    }
    复制代码

    配置方式:配置方式下,我用的是SpringBoot 1.5.4没有找到exposeProxy的选项,所以建议使用注解式.

    传统Spring配置文件

     XML

    <aop:aspectj-autoproxy expose-proxy="true"/>

    第二步(需要保证Spring对这个bean创建了代理对象,基本上涉及到Aop的方法的类,都会创建代理对象) 可以用以下代码判断

    复制代码
    /**
     * Created by laizhenwei on 19:37 2017-10-14
     */
    @Service("classImplProxy")
    @Scope(proxyMode = ScopedProxyMode.INTERFACES)
    public class ClassImplProxy implements IClass {
    
        @Override
        @Transactional
        public void sysout() {
        }
    
        //是否代理对象
        @Override
        public boolean isAopProxy() {
            return AopUtils.isAopProxy(AopContext.currentProxy());
        }
    
        //是否cglib 代理对象
        @Override
        public boolean isCglibProxy() {
            return AopUtils.isCglibProxy(AopContext.currentProxy());
        }
    
        //是否jdk动态代理
        @Override
        public boolean isJdkDynamicProxy() {
            return AopUtils.isJdkDynamicProxy(AopContext.currentProxy());
        }
    }
    复制代码

    获取代理对象    

    复制代码
      @Service
        public class ClassA{
    
            @Transactional(propagation = Propagation.REQUIRES_NEW)
            public void methodA(){
    
            }
    
            /**
             * 这里调用methodA() 的事务将会失效
             */
            public void methodB(){
                //手动获取此对象Spring的代理类
                ((ClassA)AopContext.currentProxy()).methodA();
    } }
    复制代码

    第三种方式

    直接在当前类@Autowire 或者@Resource 注入自己,然后用注入的bean 调用方法

  • 相关阅读:
    【bzoj2242】[SDOI2011]计算器
    1109解题报告
    【bzoj3239】Discrete Logging
    【bzoj2480】Spoj3105 Mod
    【POJ1811】Prime Test
    【bzoj3667】Rabin-Miller算法
    【HDU2138】How many prime numbers
    卢卡斯定理
    线段树2
    畅快的甩卖
  • 原文地址:https://www.cnblogs.com/peak-c/p/7683191.html
走看看 - 开发者的网上家园