SpringBoot CGLIB AOP解决Spring事务,对象调用自己方法事务失效.
对于像我这种喜欢滥用AOP的程序员,遇到坑也是习惯了,不仅仅是事务,其实只要脱离了Spring容器管理的所有对象,对于SpringAOP的注解都会失效,因为他们不是Spring容器的代理类,SpringAOP,就切入不了
当然可以使用原生ASPECTJ,不用SpringAOP,但是基于生态链问题,还是尽量使用SpringAOP
这里简单说一下,Spring如何选择使用CGLIB,或者是JDK代理,
Spring 代理对象,cglib,jdk的问题思考,AOP 配置注解拦截 的一些问题.为什么不要注解在接口,以及抽象方法.
简单来说,如果实现了某个接口,那么Spring就选择JDK代理(不一定),如果没有,那么就选择CGLIB代理,说起来简单,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(){ } public void methodB(){
//手动获取此对象Spring的代理类
((ClassA)AopContext.currentProxy()).methodA();
} }
第三种方式
直接在当前类@Autowire 或者@Resource 注入自己,然后用注入的bean 调用方法
SpringBoot CGLIB AOP解决Spring事务,对象调用自己方法事务失效.的更多相关文章
- Day_08【面向对象】扩展案例3_使用多态的形式创建缉毒狗对象,调用缉毒方法和吼叫方法
分析以下需求,并用代码实现: 1.定义动物类: 行为: 吼叫:没有具体的吼叫行为 吃饭:没有具体的吃饭行为 2.定义缉毒接口 行为: 缉毒 3.定义缉毒狗:犬的一种 行为: 吼叫:汪汪叫 吃饭:狗啃骨 ...
- .Net中的AOP系列之《间接调用——拦截方法》
返回<.Net中的AOP>系列学习总目录 本篇目录 方法拦截 PostSharp方法拦截 Castle DynamicProxy方法拦截 现实案例--数据事务 现实案例--线程 .Net线 ...
- 关于Hibernate查询对象调用set方法自动同步到数据库解决方案
Hibernate的get和load方法查询出的实体都是持久化对象,拿到该对象后,如果你调用了该对象的set方法,如果再同一个事务里面,那么在事务递交的时候,Hibernate会把你设置的值自动更新到 ...
- 解决spring、springMVC重复扫描导致事务失效的问题
在主容器中(applicationContext.xml),将Controller的注解排除掉 1 2 3 而在springMVC配置文件中将Service注解给去掉 1 2 3 4 因为spring ...
- 对象调用 push 方法
/* Array.prototype.push = function A(val) { this[this.length] = val; // =>this.length 在原来的基础上加1 r ...
- spring aop获取目标对象的方法对象(包括方法上的注解)
这两天在学习权限控制模块.以前看过传智播客黎活明老师的巴巴运动网视频教程,里面就讲到权限控制的解决方案,当时也只是看看视频,没有动手实践,虽说看过几遍,可是对于系统中的权限控制还是很迷茫,所以借着这次 ...
- 死磕Spring之AOP篇 - Spring 事务详解
该系列文章是本人在学习 Spring 的过程中总结下来的,里面涉及到相关源码,可能对读者不太友好,请结合我的源码注释 Spring 源码分析 GitHub 地址 进行阅读. Spring 版本:5.1 ...
- python对象调用父类的方法
#类定义 class People: #定义基本属性 name = '' age = 0 #定义私有属性,私有属性在类外部无法直接进行访问 __weight = 0 #定义构造方法 def __ini ...
- day 23 对象的名称空间 类,对象属性和方法 封装 接口提供
一.对象的特有名称空间 # 对象独有的名称空间:在产生对象时就赋初值 '''class ted: def func(): 当func里不存在参数时,调用时不需要给值 print('hah')ted.f ...
随机推荐
- Java多线程之线程的创建
好久没有更博客了,最近一直在忙工作的事情.现在终于空下来了,这2天会抓紧时间整理多线程和socket,把JavaSE结束掉. 关于多线程,首先会涉及到哪些东西呢?首先要了解线程,为什么要使用线程,线程 ...
- base64_encode与base64_decode
base64_encode 编辑 本词条缺少名片图,补充相关内容使词条更完整,还能快速升级,赶紧来编辑吧! base64_encode() returns 使用 base64 对 data 进行编码. ...
- IDEA新建Maven项目
Maven是什么? 当我们在开发一个项目的时候,不可避免地会使用到第三方的类库,而它们又可能依赖着另外的Jar包,又得引入其他Jar包,而且我们很容易就会引漏掉~然后就会报错,有时候报的错会让我们花掉 ...
- android 中string.xml中的%1$s
idView.setText(getString(R.string.estate_id, mCollectParamObj.getPlotNo())); estate_id:小区号%1$s %d ...
- input标签(待填坑)
input标签几种属性值 button:用作定义按钮 checkbox:定义复选框 file:供文件上传 hidden:定义隐藏的输入字段 image:图像形式的提交按钮 password:密码字段 ...
- 二级缓存:EHCache的使用
EHCache的使用 在开发高并发量,高性能的网站应用系统时,缓存Cache起到了非常重要的作用.本文主要介绍EHCache的使用,以及使用EHCache的实践经验. 笔者使用过多种基于Java的开源 ...
- bash启动加载过程
- es head插件通过Nginx http basic 限制访问
原文链接: http://www.sojson.com/blog/213.html
- 初学sql
bit 布尔类型 int nvarchar datetime 常用类型 nvarchar(max) 存文章(不超过5000) 字符串 用 '' . char/nchar,varchar/nvarcha ...
- CentOS上安装GitBlit服务
简单介绍 在上一篇文章中,已经简单的介绍了如何在CentOS的服务器上搭建git服务器.但是这种方式实现的服务器功能比较弱,操作起来也比较繁琐.在网上搜索了一圈,感觉Gitblit比较符合我的需求.接 ...