首先我们看一下Spring Aop的原理图
在Spring中经常使用自定义注解或是spring已经封装
好的注解,通过AOP的方式是实现代码复用,避免重复劳动。而Spring实现AOP是通过动态代理来实现的(默认有接口的情况下使用JDK的动态代理,也可以通过配置proxyTargetClass来制定使用CGLib,没有接口的情况下使用CGLib).
但是无论哪一种代理,都是在原有方法的外面包一层,通过方法外的代理层来实现AOP的逻辑。
也就是说我们首先调用的是AOP代理对象而不是目标对象。但是我们使用this.getInstalledApk()时,this表示的是当前对象,而不是代理对象,因此注解失效。
所以,解决代理无效的根本方法就是获取到代理对象,使用代理对象进行调用。

常用的方法有三种
方法一:
最简单的方法就是将调用的方法getInstalledApk()方法放在另外一个类中进行调用,而不是在一个类中同类调用,就不会出现问题了。

方法二:
从ApplicationContext中直接获取
获取ApplicationContext有多种方法:
方法2.1 使用AopContext.currentProxy()

public class A {public void serviceB() {......//此处调用的就是代理后的方法((A)AopContext.currentProxy()).serviceA();......}
}

使用AopContext.currentProxy()注意必须在程序启动时开启EnableAspectJAutoProxy注解,设置代理暴露方式为true,如下面所示:

/*** EnableAspectJAutoProxy注解两个参数作用分别为:** 一个是控制aop的具体实现方式,为true的话使用cglib,为false的话使用java的Proxy,默认为false。* 第二个参数控制代理的暴露方式,解决内部调用不能使用代理的场景,默认为false。***/
@EnableAspectJAutoProxy(proxyTargetClass = true, exposeProxy = true)
@SpringBootApplication
public class SpringAopApplication {public static void main(String[] args) {SpringApplication.run(SpringAopApplication.class, args);}
}

方法2.2 使用ApplicationContextAware
通过spring生命周期,直接将ApplicationContext注入进来

public class A implements ApplicationContextAware {private ApplicationContext applicationContext;@Overridepublic void setApplicationContext(ApplicationContext applicationContext) throws BeansException {this.applicationContext = applicationContext;}public void serviceB() {......//此处调用的就是代理后的方法applicationContext.getBean(A.class).serviceA();......}
}

方法三:
在实现类中注入自身,这个有点取巧。还是以上面serviceB()为例,我们如果调用this.serviceA(),this指向对象本身、不会指向代理后的对象,因此肯定不可以,但我们可以让spring提供给我们代理后的对象:

@Service
public class Child implements IChild {//通过spring将代理后对象注入到self变量@Autowiredprivate Child child;@Overridepublic Map eat() throws GendorException {String name = child.name();//此处调用的就是代理后的方法System.out.println(name);return null;}@SysLogpublic String name (){return "zhangjiguo";}
}

总结:
(1).在一个类内部调用时,被调用方法的 AOP 声明将不起作用。Spring 事务管理注解 @Transactional 也一样。

(2).对于基于接口动态代理的 AOP 事务增强来说,由于接口的方法都必然是 public 的,这就要求实现类的实现方法也必须是 public 的(不能是 protected、private 等),同时不能使用 static 的修饰符。所以,可以实施接口动态代理的方法只能是使用 public 或 public final 修饰符的方法,其他方法不可能被动态代理,相应的也就不能实施 AOP 增强,换句话说,即不能进行 Spring 事务增强了。

(3).基于 CGLib 字节码动态代理的方案是通过扩展被增强类,动态创建其子类的方式进行 AOP 增强植入的。由于使用 final、static、private 修饰符的方法都不能被子类覆盖,相应的,这些方法将无法实施 AOP 增强。所以方法签名必须特别注意这些修饰符的使用,以免使方法不小心成为事务管理的漏网之鱼。

(4).该例中的方法符合上述条件,但注解仍然失效,主要原因是在于同一类中的方法互相调用,调用者指向当前对象,所以无论是接口代理还是 cglib 代理都无法织入增强实现。

Spring AOP 同类调用失效问题及解决方案相关推荐

  1. 探究Spring AOP 同类调用失效问题

    扯一下沟通 本来这篇文章是想写关于职场上的沟通的,尽管我也是一个初入职场的小白.但是发现时间不太够,只好作罢,后面再补上吧.关于沟通,我总结起来就是"沟通渠道要畅通,沟通要主动,沟通要高效& ...

  2. Spring AOP注解为什么失效?90%Java程序员不知道

    转载自 Spring AOP注解为什么失效?90%Java程序员不知道 使用Spring Aop注解的时候,如@Transactional, @Cacheable等注解一般需要在类方法第一个入口的地方 ...

  3. java 自定义异常 未回滚_抛出自定义异常,spring AOP事务不回滚的解决方案

    spring AOP 默认对RuntimeException()异常或是其子类进行事务回滚,也就是说 事务回滚:throw new RuntimeException("xxxxxxxxxxx ...

  4. SpringAOP同类调用失效(事务失效)

    项目场景: 同一个 ServiceA 中有B()方法.C()方法,在 ServiceA 中B()调用C()时,事务注解@Transactional不生效 @Service public class S ...

  5. 在线记录源码调试之@EnableAspectJAutoProxy与Spring AOP(三)调用被代理方法userServiceImpl.save(user)

    测试用例1 连接点 @Component public class UserServiceImpl implements UserService {@Overridepublic void save( ...

  6. Spring AOP方法分析

    Spring AOP方法分析 此示例显示如何配置Spring AOP方法概要分析.我们可以在任何服务(或其他)类中使用Spring AOP和任何方法,而无需在任何服务类中编写任何一行分析代码.面向方面 ...

  7. 史上最烂 spring aop 原理分析

    盗引·中篇·spring aop spring aop: jdk 动态代理和 cglib 动态代理的特点.区别.使用方式.原理及各自对反射的优化.二者在 spring 中的统一.通知顺序.从 @Asp ...

  8. 同类调用AOP失效问题

    使用aop代理对象,我们的到的原始对象实际上是一个他的代理对象 如: 结果: 这里可以得知,AOP是通过代理对象调用切入点(被通知的连接点),实现切面关系,AOP通知才会生效. 今天就疏忽了,连接点调 ...

  9. spring同类调用事务不生效-原因及三种解决方式

    spring提供的声明式事务注解@Transactional,极大的方便了开发者管理事务,无需手动编写开启.提交.回滚事务的代码. 但是也带来了一些隐患,如果注解使用不当,可能导致事务不生效,最终导致 ...

最新文章

  1. R语言β分布函数(dbeta、pbeta、qbeta、rbeta)实战
  2. 二代数据 模拟软件wgsim
  3. Redis 5种数据结构
  4. SQL Server存储过程(转载)
  5. 区块链100问 第一问
  6. 最容易扩展的光立方程序设计
  7. 基于STM32F103驱动TM1640LED数码管代码实现
  8. 自媒体原创度检测工具有哪些?这几个可以免费用
  9. WinMTR-路由追踪软件
  10. Sicily 2014 Dairy Queen
  11. Python学习笔记--Python 爬虫入门 -17-5 js 加密 (和有道词典的瓜葛)
  12. matlab如何绘制相关系数热力图,相关系数矩阵与热力图heatmap
  13. ActiveMQ学习 (一) JSM基本概念
  14. js escape()_unescape().html
  15. 无法正常打开网页的解决方法(情况一)
  16. 【数学建模】十二(最后一篇):MATLAB CUMCM真题求解实例三:机理建模型
  17. 腾讯:互联网金融行业HBase实践与创新
  18. 已官宣:测试人员抄小道进腾讯的机会来了!
  19. 科普:alphago是什么
  20. 2020年高级Java程序员面试题汇总,含答案总结

热门文章

  1. 计算机网络——学习笔记
  2. 盘点HR日常工作数据计算大全
  3. 我们进入“超空间”时代
  4. 狼叔:F2C 能否让前端像运营配置一样开发?
  5. Android 优秀文章收集整理集合
  6. 光场相机模拟程序解读
  7. 一款常用文档生成工具:Doxygen
  8. seo-移动站优化问题修改针对落地页规范
  9. 直链站php源码,源码库分享PHP版百度网盘直链/外链源码
  10. 分式化简 设计算法 c语言,化简分式(对小数有用)