当前位置: 首页 > news >正文

Spring-AOP不生效之内部方法调用

Spring-AOP

现象:接口实现类中有两个,doMethod1()调用了doMethod2(),此时对于AOP,如果现在外部对象调用doMethod1()方法的时候,会发现只有doMethod1()方法执行被拦截,AOP生效,而doMethod1()内部调用doMethod2()时并没有被拦截;外部对象单独调用doMethod1()时会被拦截。

@Service
public class JdkProxyDemoServiceImpl implements IJdkProxyService {@Overridepublic void doMethod1() {doMethod2()System.out.println("JdkProxyServiceImpl.doMethod1()");}@Overridepublic String doMethod2() {System.out.println("JdkProxyServiceImpl.doMethod2()");return "hello world";}
}

分析: 拦截器的实现原理就是动态代理,实现AOP机制。Spring的代理实现有两种:一是基于 JDK Dynamic Proxy 技术而实现的;二是基于 CGLIB 技术而实现的。如果目标对象实现了接口,在默认情况下Spring会采用JDK的动态代理实现AOP

//JDK动态代理生成的JdkProxyDemoServiceImpl 的代理类
@Service
public class JdkProxyDemoServiceProxy implements IJdkProxyService {private  IJdkProxyService  iJdkProxyService;public void setIJdkProxyService(IJdkProxyService iJdkProxyService) {  this.iJdkProxyService= iJdkProxyService;  }  public void doMethod1() {//前置通知doBefore() iJdkProxyService.doMethod1();}public String doMethod2() {//前置通知doBefore() return iJdkProxyService.doMethod2();}private void doBefore() { System.out.println(" 前置通知...");  }  
}

当使用时,从IOC容器中获取的Bean对象都是代理对象,而不是Bean对象本身,由于this关键字应用的并不是该Bean对象的对象,而是其本身,因此此时Spring AOP是不能拦截到这些被嵌套调用的方法的。

//当获取Bean对象使用时//spring容器创建代理对象
IJdkProxyService  iJdkProxyService = new IJdkProxyServiceImpl();JdkProxyDemoServiceProxy  serviceProxy  = new JdkProxyDemoServiceProxy ()
serviceProxy.setIJdkProxyService(iJdkProxyService);
IJdkProxyService iJdkProxyService = (IJdkProxyService) serviceProxy;iJdkProxyService.doMethod1();

解决:

1、修改类,把内部自调用改掉。

2、将this.doMethod2()替换为:((IJdkProxyService ) AopContext.currentProxy()).doMethod2();此时需要修改springaop配置:

// 指示是否创建基于子类(CGLIB)的代理,而不是创建基于标准Java接口的代理。 默认值是{@code false}。
@EnableAspectJAutoProxy(proxyTargetClass = true)

3、使用SpringUtil.getBean("iJdkProxyService ").doMethod2();

@Component
public class SpringUtil implements ApplicationContextAware {private static ApplicationContext applicationContext;public SpringUtil springUtil() {return new SpringUtil();}@Overridepublic void setApplicationContext(ApplicationContext applicationContext) throws BeansException {if(SpringUtil.applicationContext == null) {SpringUtil.applicationContext = applicationContext;}}//获取applicationContextpublic static ApplicationContext getApplicationContext() {return applicationContext;}//通过name获取 Bean.public static Object getBean(String name){return getApplicationContext().getBean(name);}//通过class获取Bean.public static <T> T getBean(Class<T> clazz){return getApplicationContext().getBean(clazz);}//通过name,以及Clazz返回指定的Beanpublic static <T> T getBean(String name,Class<T> clazz){return getApplicationContext().getBean(name, clazz);}}

相关文章:

  • 【Android】画面卡顿优化列表流畅度一
  • uboot - 驱动开发 - dw watchdog
  • 无梯度强化学习:使用遗传算法进化代理
  • 【服务配置文件详解】补充rsyslog服务的配置文件翻译解读
  • 【hcie-cloud】【5】华为云Stack规划设计之华为云Stack标准化配置、缩略语【下】
  • 前端Vue 结合xlxs库实现解析excel文件,并动态组装表头!
  • CMakeFiles文件夹有什么用
  • Xmake v2.8.5 发布,支持链接排序和单元测试
  • 5G毫米波通信中的关键技术
  • 3D物理模拟和视觉特效软件SideFX Houdini mac中文介绍
  • 什么是记忆能力与泛化能力
  • Mac电脑Visio文件编辑查看软件推荐Visio Viewer for Mac
  • C++多态特性
  • 揭秘南卡开放式耳机创新黑科技,核心技术剑指用户痛点
  • RAW图像处理软件Capture One 23 Enterprise mac中文版功能特点
  • 【附node操作实例】redis简明入门系列—字符串类型
  • docker容器内的网络抓包
  • Java程序员幽默爆笑锦集
  • Magento 1.x 中文订单打印乱码
  • Object.assign方法不能实现深复制
  • 规范化安全开发 KOA 手脚架
  • 湖南卫视:中国白领因网络偷菜成当代最寂寞的人?
  • 优化 Vue 项目编译文件大小
  • “十年磨一剑”--有赞的HBase平台实践和应用之路 ...
  • 关于Kubernetes Dashboard漏洞CVE-2018-18264的修复公告
  • #预处理和函数的对比以及条件编译
  • (1/2) 为了理解 UWP 的启动流程,我从零开始创建了一个 UWP 程序
  • (PyTorch)TCN和RNN/LSTM/GRU结合实现时间序列预测
  • (TipsTricks)用客户端模板精简JavaScript代码
  • (附源码)apringboot计算机专业大学生就业指南 毕业设计061355
  • (附源码)python房屋租赁管理系统 毕业设计 745613
  • (附源码)springboot 基于HTML5的个人网页的网站设计与实现 毕业设计 031623
  • (附源码)springboot教学评价 毕业设计 641310
  • (个人笔记质量不佳)SQL 左连接、右连接、内连接的区别
  • (免费领源码)python#django#mysql校园校园宿舍管理系统84831-计算机毕业设计项目选题推荐
  • (强烈推荐)移动端音视频从零到上手(下)
  • (三分钟了解debug)SLAM研究方向-Debug总结
  • (转)人的集合论——移山之道
  • *** 2003
  • ****** 二 ******、软设笔记【数据结构】-KMP算法、树、二叉树
  • . NET自动找可写目录
  • .net 7 上传文件踩坑
  • .net core MVC 通过 Filters 过滤器拦截请求及响应内容
  • .NET Core 实现 Redis 批量查询指定格式的Key
  • .Net 访问电子邮箱-LumiSoft.Net,好用
  • .NET 设计一套高性能的弱事件机制
  • .NET 中使用 Mutex 进行跨越进程边界的同步
  • .NET序列化 serializable,反序列化
  • /etc/sudoer文件配置简析
  • @Transactional 竟也能解决分布式事务?
  • [Android]Android P(9) WIFI学习笔记 - 扫描 (1)
  • [BZOJ] 2006: [NOI2010]超级钢琴
  • [BZOJ]4817: [Sdoi2017]树点涂色
  • [BZOJ3223]文艺平衡树
  • [CUDA手搓]从零开始用C++ CUDA搭建一个卷积神经网络(LeNet),了解神经网络各个层背后算法原理