• 导读
  • 概述
  • 带有横切逻辑的实例
  • JDK动态代理
  • CGLib动态代理
  • 代理知识小结

导读

Spring-AOP基础知识

Java-JDK动态代理

Java-CGLib动态代理


概述

Spring AOP 使用动态代理技术在运行期织入增强的代码.

为了解密SpringAOP底层的工作机制,我们需要先学习下涉及到的JAVA知识。

Spring使用两种代理机制:

  1. 一种是基于JDK的动态代理
  2. 另一种是基于CGLib的动态代理。

之所以需要两种代理,是因为JDK本身只能提供接口的代理,而不支持类的代理。


带有横切逻辑的实例

代码已托管到Github—> https://github.com/yangshangwei/SpringMaster

来看个实例,我们以性能监控为例子,在调用每个目标类方法时启动方法的性能监视,在目标类方法调用完成时记录方法的花费时间。

我们首先来看下包含性能监视横切代码的 ForumService

package com.xgj.aop.base.instance;/*** * * @ClassName: ForumServiceImpl* * @Description: ForumService实现类* * @author: Mr.Yang* * @date: 2017年8月12日 下午4:14:30*/
public class ForumServiceImpl implements ForumService {@Overridepublic void removeTopic(int topicId) {// 1-(1)开始对removeTopic方法的监控PerformanceMonitor.begin("removeTopic");// 模拟业务逻辑System.out.println("模拟删除Topic");try {Thread.currentThread().sleep((long) (Math.random() * 1000 * 10));} catch (InterruptedException e) {e.printStackTrace();}// 1-(2)结束对removeTopic方法的监控PerformanceMonitor.end("removeTopic");}@Overridepublic void removeForum(int forumId) {// 2-(1)开始对removeForum法的监控PerformanceMonitor.begin("removeForum");// 模拟业务逻辑System.out.println("模拟删除forum");try {Thread.currentThread().sleep((long) (Math.random() * 1000 * 10));} catch (InterruptedException e) {e.printStackTrace();}// 2-(2)结束对removeForum法的监控PerformanceMonitor.end("removeForum");}}

ForumServiceImpl 实现了ForumService接口。

package com.xgj.aop.base.instance;/*** * * @ClassName: ForumService* * @Description: ForumService接口* * @author: Mr.Yang* * @date: 2017年8月12日 下午4:13:31*/
public interface ForumService {/*** * * @Title: removeTopic* * @Description: 根据topicId删除Topic* * @param topicId* * @return: void*/void removeTopic(int topicId);/*** * * @Title: removeForum* * @Description: 根据forumId删除Forum* * @param forumId* * @return: void*/void removeForum(int forumId);
}

其中1-(1) 1-(2) 2-(1)2-(2)标注的是具有横切逻辑特征的代码,每个Service类和每个业务方法体的前后都执行相同的代码逻辑:方法启动前启用PerformanceMonitor,方法调用后通知PerformanceMonitor结束性能监视并记录性能监视结果。

PerformanceMonitor是性能监视的实现类

package com.xgj.aop.base.instance;public class PerformanceMonitor {// 通过一个ThreadLocal保存与调用线程相关的性能监视信息private static ThreadLocal<MethoPerformance> performanceLocal = new ThreadLocal<MethoPerformance>();/*** * * @Title: begin* * @Description: 启动对某一目标方法的性能监视* * @param method* * @return: void*/public static void begin(String method) {System.out.println("begin to monitor:" + method);MethoPerformance methoPerformance = new MethoPerformance(method);performanceLocal.set(methoPerformance);}/*** * * @Title: end* * @Description: 输出性能监视结果* * @param method* * @return: void*/public static void end(String method) {System.out.println("finish monitor:" + method);MethoPerformance methoPerformance = performanceLocal.get();// 打印出方法性能监视的结果信息methoPerformance.printPerformance();}
}

我们通过ThreadLocal将非线程安全类改造为线程安全的类。

PerformanceMonitor类中两个方法 begin和end ,其中method规定为目标类方法的全限定名。 两个方法必须配套使用。

用于记录性能监视信息的MethoPerformance 如下:

package com.xgj.aop.base.instance;public class MethoPerformance {private long beginTime;private long endTime;private String methodName;/*** * * @Title:MethoPerformance* * @Description:构造函数* * @param methodName*/public MethoPerformance(String methodName) {super();this.methodName = methodName;this.beginTime = System.currentTimeMillis();}/*** * * @Title: printPerformance* * @Description: 计算耗时* * * @return: void*/public void printPerformance() {endTime = System.currentTimeMillis();long cost = endTime - beginTime;System.out.println(methodName + " costs " + cost / 1000 + "秒\n");}
}

测试类:

package com.xgj.aop.base.instance;public class ForumServiceTest {public static void main(String[] args) {ForumService forumService = new ForumServiceImpl();forumService.removeTopic(1);forumService.removeForum(2);}}

运行结果:

问题:通过这个实例,我们可以看到当某个方法需要进行性能监视时,必须调整方法代码,在方法体前后分别添加开启性能监视和结束性能监视的代码。 这些非业务逻辑的性能监视代码破坏了业务实现类中业务逻辑的纯粹性。

改进:我们希望通过代理的方式将业务类方法中开启和结束性能监视的横切代码从业务类中完全移除,并通过JDK或者CGLib动态代理技术将横切代码动态的织入到目标方法的相应位置。


JDK动态代理

详情请访问另一篇博客: Java-JDK动态代理


CGLib动态代理

详情请访问另一篇博客: Java-CGLib动态代理


代理知识小结

Spring AOP的底层就是通过使用JDK或者CGLib动态代理技术为目标Bean织入横切逻辑的。

总结一下动态创建代理对象:

虽然通过PerformanceHandle或者CglibProxy实现了性能监视横切逻辑的动态织入,但是这种实现方式有3个明显需要改进的地方

  1. 目标类的所有方法都添加了性能监视横切逻辑,而有的时候这并不是我们所期望的,我们可能只希望对业务类中的某些特定方法添加横切逻辑

  2. 通过硬编码的方式指定了织入横切逻辑的织入点,即在目标类业务方法的开始和结束前织入代码

  3. 手工编写代理实例的创建过程,在为不同类创建代理时,需要分别编写相应的创建代码,无法做到通用。

以上3个问题在AOP中占有重要的地位,因为SpringAOP的主要工作就是围绕以上3点展开的: Spring AOP 通过Pointcut(切点)指定在哪些类的哪些方法上织入横切逻辑,通过Advice(增强)描述横切逻辑和方法的具体织入点(方法前、方法后、方法的两端等)。

此外,Spring通过Advisor(切面)将Point和Advice组装起来,有了Advisor信息,SPring就可以利用JDK或者CGLib动态代理结束采用统一的方式为目标Bean创建织入切面的代理对象了。

对应singleton的代理对象或者具有实例池的代理,因无需频繁创建对象,比较适合采用CGLib动态代理技术,反之则比较适合采用JDK动态代理技术

Spring-AOP基础知识相关推荐

  1. 了解动态代理:Spring AOP基础

    为什么选择AOP: 要了解AOP(面向方面​​的编程),我们需要了解软件开发中的"横切关注点". 在每个项目中,都有一定数量的代码在多个类,多个模块中重复执行,例如几乎所有类和所有 ...

  2. 2021 版 Spring Boot 基础知识复习手册(2w字,建议收藏)

    点击上方 好好学java ,选择 星标 公众号重磅资讯,干货,第一时间送达 今日推荐:分享一套基于SpringBoot和Vue的企业级中后台开源项目,这个项目有点哇塞!个人原创100W +访问量博客: ...

  3. SSM框架笔记10:Spring AOP基础

    Spring AOP基础   AOP:Aspect-Oriented Programming 面向切面编程.   Spring的AOP作用在于解耦.AOP让一组类共享相同的行为(比如事务管理.日志管理 ...

  4. Spring AOP基础组件 Pointcut

    相关阅读 Spring AOP基础组件 Advice Spring AOP基础组件 Advisor 简介 定义了切面的匹配点,即哪些类的哪些方法:在Spring AOP中匹配点主要是class(Cla ...

  5. Spring AOP基础组件 Advisor

    相关阅读 Spring AOP基础组件 Pointcut Spring AOP基础组件 Advice 简介 持有AOP Advice和决定Advice适用性的过滤器(比如Pointcut)的基础接口: ...

  6. Spring AOP基础组件 Joinpoint

    相关阅读 Spring AOP基础组件 Pointcut Spring AOP基础组件 Advice Spring AOP基础组件 AopProxy 简介 Joinpoint表示通用的运行时连接点: ...

  7. Spring框架基础知识

    本人博客文章网址:https://www.peretang.com/basic-knowledge-of-spring-framework/ Spring框架简介 Spring , 一个开源的框架 , ...

  8. Spring集成基础知识

    本文是我们名为" EAI的Spring集成 "的学院课程的一部分. 在本课程中,向您介绍了企业应用程序集成模式以及Spring Integration如何解决它们. 接下来,您将深 ...

  9. 2022年Java应届生面试之Spring框架基础知识

    前言:工作的原因,最近没有及时更新相关系列.很抱歉!在复习Spring框架的同时也别忘了j2ee的相关知识理论wo~ 大家好!我是JAVA 中的Spring框架,我是一个开源的容器性质的轻量级框架. ...

  10. Spring Aop基础使用

    说到Spring,想必大家一定就马上想到了,哦Spring不就是帮助管理Bean对象,封装数据源,提供事务管理的东西么.的确,平常在使用Spring的时候,用到最多的就是Spring提供的这些功能了, ...

最新文章

  1. Blender三维建筑场景动画制作学习教程
  2. F#创建者Don Syme谈F#设计原则
  3. 日期相减计算年_函数 | Excel有个“秘密”函数,计算年龄工龄特方便
  4. 随想(二):简化别人的工作,就是简化自己的工作,节省自己的时间
  5. 用python重构策略模式
  6. WPF连接WF4的问题
  7. 第一次作业 四班15
  8. Asp.Net中WebApi多图片上传(附前后端代码)
  9. 利用Python连接MySQL将表单转化为DataFrame
  10. 记录自己的心路文字~
  11. python压缩视频文件_python压缩图片和视频
  12. 日本人布置工作至少说5遍
  13. 大数据可视化 课堂笔记-1
  14. Firefox OS简介
  15. 如何恢复已删除的照片
  16. 使用cert-manager给阿里云的DNS域名授权SSL证书
  17. 最新Ubuntu20.04安装指南(防踩坑版)
  18. C# SuperSocket 手把手教你入门 傻瓜教程---5(探索自定义AppServer、AppSession,Conmmand,用配置文件App.comfig启动服务器)
  19. 常用的javascript实例
  20. win10计算机找不到家庭组,win10专业版没有家庭组怎么办?一招帮你解决问题

热门文章

  1. 虚拟主机跟php,php虚拟主机和服务器(云服务器跟虚拟主机)
  2. C++输入输出类的层次
  3. sql 查询嵌套数组
  4. cifar-10 cnn 分类
  5. wireshark网络分析就这么简单 pdf_才知道,PDF、Excel、Word互转这么简单?涨知识了...
  6. R语言应用实战-基于R的因子分析(以上市公司数据为例)
  7. 深度学习核心技术精讲100篇(六十一)-TikTok抖音国际版留存背后的数据和算法推演
  8. Hadoop学习之MapReduce(四)
  9. Python编程基础:第五十节 海象运算符Walrus Operator
  10. Netty 学习和进阶策略