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

Spring基础之AOP和代理模式

文章目录

    • 理解AOP
      • AOP的实现原理
    • AOP代理模式
      • 静态代理
      • 动态代理
        • 1-JDK动态代理
        • 2-CGLIB动态代理
    • 总结

理解AOP

OOP - - Object Oriented Programming 面向对象编程
AOP - - Aspect Oriented Programming 面向切面编程
AOP是Spring提供的关键特性之一。AOP即面向切面编程,是OOP编程的有效补充。使用AOP技术,可以将一些系统性相关的编程工作,独立提取出来,独立实现,然后通过切面切入进系统。从而避免了在业务逻辑的代码中混入了很多的系统性相关的逻辑–比如:事务管理、日志记录、权限管理等,从而达到了将不同的关注点分离出来松耦合的效果。

AOP的实现原理

AOP的实现原理就是代理模式----其关键点是AOP框架自动创建的AOP代理
AOP代理分为静态AOP代理和动态AOP代理:

  1. 静态AOP代理 –– 是指AspectJ实现的AOP代理,它是将切面代码直接编译到Java字节码文件中,发生在编译时。
  2. 动态AOP代理 –– 是指将切面代码进行动态织入实现的AOP代理,发生在运行时。Spring的AOP即为动态AOP实现技术为:JDK提供的动态代理技术和CGLIB(Code Generation Library动态字节码增强技术)。尽管实现技术不一样,但都是基于代理模式,都是生成一个代理对象。

AOP代理模式

代理模式的核心作用就是通过代理,控制对被代理的目标对象的访问。它的设计思路是:定义一个抽象角色{接口},让代理角色和真实角色分别去实现它。

真实角色:实现抽象角色,定义真实角色所要实现的业务逻辑,供代理角色调用。它只关注真正的业务逻辑。

代理角色:实现抽象角色,是真实角色的代理,通过真实角色的业务逻辑方法来实现抽象方法,并在前后可以附加自己的操作。
代理模式实现歌星演出场景

静态代理

要求被代理类和代理类同时实现相应的一套接口,通过代理类调用重写接口的方法,实际上调用的是原始对象的同样的方法。如下图

在这里插入图片描述

/*** 明星接口*/
public interface Star {void sing();
}
/*** 真实明星类*/
public class RealStar implements Star{@Overridepublic void sing() {System.out.println("明星本人开始唱歌...");}
}/*** 明星静态代理类*/
public class ProxyStar implements Star{private Star star; //接收明星对象/*** 通过构造方法传进来真实的明星对象* @param star*/public ProxyStar(Star star) {this.star = star;}@Overridepublic void sing() {System.out.println("明星代理先进行商务谈判...");//真实明星唱歌star.sing();System.out.println("明星演出完,代理收款...");}
}

这样的话,逻辑就非常清晰了。在代理类中,可以看到,维护了一个Star对象,通过构造方法传进来一个真实的Star对象给其赋值,
然后在唱歌这个方法里,使用真实对象来唱歌。所以说面谈、收钱都是由代理对象来实现的,唱歌是代理对象让真实对象来做。

/*** 测试客户端*/
public class TestClient {/*** 测试静态代理结果* @param args*/public static void main(String[] args) {Star realStar = new RealStar(); //创建真实对象Star proxy = new ProxyStar(realStar); //创建代理对象proxy.sing();}
}

静态代理的优缺点:
优点:
  1.被代理的业务类只需要做好自己的业务,实现了责任分离,保证了业务类的重用性
  2.将业务类隐藏起来,起到了保护作用
缺点:
  1.代理对象的某个接口只服务于某一个业务对象,每个真实对象都得创建一个代理对象
  2.如果接口增加一个方法,除了所有实现类需要实现这个方法外,代理类也需要实现,增加了代码的复杂度和成本

动态代理

在程序运行时由JVM通过反射机制动态的创建出代理对象的字节码。代理对象和真实对象的关系是在程序运行时才确定

1-JDK动态代理

JDK动态代理是使用java.lang.reflect包中的Proxy类与InvocationHandler接口来完成的,要使用JDK动态代理,必须要定义接口

API分析:
(1) java.lang.reflect.Proxy 类|-Java动态代理机制生成的所有动态代理类的父类,它提供了一组静态方法来为一组接口动态地生成代理类及其对象。public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces,InvocationHandler hanlder)
方法职责:为指定类加载器、一组接口及调用处理器  生成动态代理类实例 
参数:loader        :类加载器interfaces        :目标(真实)对象实现的接口hanlder        :代理执行处理器
返回:动态生成的代理对象
(2) java.lang.reflect.InvocationHandler接口:
public Object invoke(Object proxy, Method method, Object[] args)
方法职责:负责集中处理动态代理类上的所有方法调用
参数: proxy :  生成的代理对象method: 当前调用的真实方法对象args:    当前调用方法的实参
返回: 真实方法的返回结果
jdk动态代理操作步骤 实现InvocationHandler接口,创建自己增强代码的处理器。
② 给Proxy类提供ClassLoader对象和代理接口类型数组,创建动态代理对象。
③ 在处理器中实现增强操作。

示例:

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;/*** JDK动态代理处理类*/
public class JdkProxyHandler implements InvocationHandler {/*** 用来接收真实明星对象*/private Object realStar;/*** 传入真实明星对象,动态创建一个代理** @param realStar* @return*/public Object bind(Object realStar) {this.realStar = realStar;return Proxy.newProxyInstance(realStar.getClass().getClassLoader(),realStar.getClass().getInterfaces(), this);}/*** 当调用代理对象的方法时,会调用此方法** @param proxy* @param method* @param args* @return* @throws Throwable*/@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println("明星代理先进行谈判...");Object result = method.invoke(realStar, args); //真实对象明星唱歌System.out.println("演出完,代理收款...");return result;}
}
/*** 测试Jdk动态代理客户端*/
public class TestJdkProxyClient {public static void main(String[] args) {Star realStar = new RealStar(); //真实对象//创建一个代理对象实例Star proxy = (Star)new JdkProxyHandler().bind(realStar);//代理对象调用方法proxy.sing();}
}

相对于静态代理,JDK 动态代理大大减少了我们的开发任务,同时减少了对业务接口的依赖,降低了耦合度

2-CGLIB动态代理

由上面的分析可知,JDK 实现动态代理需要实现类通过接口定义业务方法,那对于没有接口的类,如何实现动态代理呢,这就需要 CGLIB 了。

  • CGLIB(Code Generation Library),是一个代码生成的类库,可以在运行时动态的生成某个类的子类.
  • CGLIB动态代理是针对没有接口的类进行的代理,和JDK动态代理的区别是获取代理对象的方法不一样
/*** 真实明星类*/
public class RealStar{public void sing() {System.out.println("明星本人开始唱歌...");}
}import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;import java.lang.reflect.Method;/*** Cglib代理处理类*/
public class CglibProxyHandler implements MethodInterceptor {/*** 维护的目标对象*/private Object realStar;/***  Enhancer类是CGLIB中的一个字节码增强器,它可以方便的对你想要处理的类进行扩展*/private Enhancer enhancer = new Enhancer();/*** 根据被代理对象的类型 ,动态创建一个代理对象* @param realStar* @return*/public Object bind(Object realStar){
this.realStar = realStar;enhancer.setSuperclass(realStar.getClass()); //使用增强器,设置被代理对象为父类enhancer.setCallback(this);  //设置回调方法,拦截器//动态创建一个代理类对象,并返回return enhancer.create();}/***  当调用代理对象的方法时,会调用此方法进行拦截* @param proxy 代理对象* @param method 需要增强的方法* @param objects 需要增强方法的参数* @param methodProxy  需要增强的方法的代理* @return 方法执行后的返回值* @throws Throwable*/@Overridepublic Object intercept(Object object, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {System.out.println("代理明星先进行演出谈判...");//invokeSuper方法调用的对象已经是增强了Object result = methodProxy.invokeSuper(object,args); //明星唱歌System.out.println("演出完成,代理去收款...");return result;}
}/*** 测试Cglib动态代理客户端*/
public class TestCglibProxyClient {public static void main(String[] args) {RealStar realStar = new RealStar(); //真实对象//创建一个代理对象实例RealStar proxy = (RealStar) new CglibProxyHandler().bind(realStar);//代理对象调用方法proxy.sing();}
}

关于CGLIB 动态代理总结:

  • CGLib所创建的动态代理对象在实际运行时候的性能要比JDK动态代理高不少,但是CGLIB 创建代理对象时所花费的时间却比JDK多得多,所以对于单例singleton的对象,因为无需频繁创建对象,用 CGLIB 合适,反之使用JDK方式要更为合适一些。
  • CGLIB是通过继承的方式做的动态代理,因此如果某个类被标记为final,那么它是无法使用CGLIB做动态代理的,诸如private的方法也是不可以作为切面的。

小结
Spring AOP 中的代理使用逻辑:如果目标对象实现了接口,默认情况下会采用 JDK 的动态代理实现 AOP;如果目标对象没有实现了接口,则采用 CGLIB 库,Spring 会自动在 JDK 动态代理和 CGLIB 动态代理之间转换

总结

  • AOP面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术
  • 使用AOP技术,可以将一些系统性相关的编程工作,独立提取出来,独立实现,然后通过切面切入进系统。
  • Spring的AOP为动态AOP,实现的技术为: JDK提供的动态代理技术 和 CGLIB(动态字节码增强技术)
  • 代理模式--官方的定义为“为其他对象提供一种代理以控制对这个对象的访问”
  • java中有静态代理、JDK动态代理、CGLib动态代理的方式。静态代理指的是代理类是在编译期就存在的,相反动态代理则是在程序运行期动态生成的

相关文章:

Spring基础之AOP和代理模式

文章目录 理解AOPAOP的实现原理 AOP代理模式静态代理动态代理1-JDK动态代理2-CGLIB动态代理 总结 理解AOP OOP - - Object Oriented Programming 面向对象编程 AOP - - Aspect Oriented Programming 面向切面编程 AOP是Spring提供的关键特性之一。AOP即面向切面编程&#xff0…...

二层交换机和三层交换机区别

01、二层交换机 二层交换机&#xff0c;也被称为数据链路层交换机&#xff0c;是在OSI模型的数据链路层&#xff08;第二层&#xff09;进行数据交换的设备。它基于MAC&#xff08;Media Access Control&#xff09;地址来转发数据包&#xff0c;实现局域网内部的数据传输 1、…...

【Java程序设计】【C00267】基于Springboot的在线考试系统(有论文)

基于Springboot的在线考试系统&#xff08;有论文&#xff09; 项目简介项目获取开发环境项目技术运行截图 项目简介 本系统是基于Springboot的在线考试系统&#xff1b;本系统主要分为管理员、教师和学生三种角色&#xff1b; 管理员登录系统后&#xff0c;可以对首页&#x…...

【LeetCode】416. 分割等和子集(中等)——代码随想录算法训练营Day41

题目链接&#xff1a;416. 分割等和子集 题目描述 给你一个 只包含正整数 的 非空 数组 nums 。请你判断是否可以将这个数组分割成两个子集&#xff0c;使得两个子集的元素和相等。 示例 1&#xff1a; 输入&#xff1a;nums [1,5,11,5] 输出&#xff1a;true 解释&#x…...

51单片机学习(4)-----独立按键进一步控制LED灯

前言&#xff1a;感谢您的关注哦&#xff0c;我会持续更新编程相关知识&#xff0c;愿您在这里有所收获。如果有任何问题&#xff0c;欢迎沟通交流&#xff01;期待与您在学习编程的道路上共同进步。 目录 一. 独立按键灵活控制LED 程序一&#xff1a;单个独立按键控制多个…...

Redis 学习笔记 3:黑马点评

Redis 学习笔记 3&#xff1a;黑马点评 准备工作 需要先导入项目相关资源&#xff1a; 数据库文件 hmdp.sql后端代码 hm-dianping.zip包括前端代码的 Nginx 启动后端代码和 Nginx。 短信登录 发送验证码 PostMapping("code") public Result sendCode(RequestP…...

电脑恢复删除数据的原理和方法

在恢复数据的时候&#xff0c;很多人都会问&#xff0c;为什么删除的数据还能恢复&#xff1f;本篇和大家一起了解下硬盘上数据的存储方式&#xff0c;文件被删除的时候具体发生了什么&#xff0c;帮助大家理解数据恢复的基本原理。最后还会分享一个好用的数据恢复工具并附上图…...

SpringBoot和SpringCloud的区别,使用微服务的好处和缺点

SpringBoot是一个用于快速开发单个Spring应用程序的框架&#xff0c;通过提供默认配置和约定大于配置的方式&#xff0c;快速搭建基于Spring的应用。让程序员更专注于业务逻辑的编写&#xff0c;不需要过多关注配置细节。可以看成是一种快速搭建房子的工具包&#xff0c;不用从…...

32单片机基础:GPIO输出

目录 简介&#xff1a; GPIO输出的八种模式 STM32的GPIO工作方式 GPIO支持4种输入模式&#xff1a; GPIO支持4种输出模式&#xff1a; 浮空输入模式 上拉输入模式 下拉输入模式 模拟输入模式&#xff1a; 开漏输出模式&#xff1a;&#xff08;PMOS无效&#xff0c;就…...

【linux】查看openssl程序的安装情况

【linux】查看openssl程序的安装情况 1、查看安装包信息 $ rpm -qa |grep openssl 2、安装路径 $ rpm -ql openssl $ rpm -ql openssl-libs $ rpm -ql openssl-devel 3、相关文件和目录 /usr/bin/openssl /usr/include/openssl /usr/lib64/libssl.so.* /usr/lib64/libcrypto…...

高防服务器主要运用在哪些场景?

高防服务器主要是用来防御DDOS攻击的服务器&#xff0c;能够为客户提供安全维护&#xff0c;高防服务器能够帮助网站拒绝服务攻击&#xff0c;定时扫描网络主节点&#xff0c;进行查找可能会出现的安全漏洞的服务类型&#xff0c;高防服务器也会根据不同的IDC机房环境来提供硬防…...

Eureka:微服务中的服务注册与发现机制

引言 在微服务架构中&#xff0c;由于服务数量巨大并且各个服务的实例可能会频繁上下线&#xff0c;因此服务注册和发现机制至关重要。 那么&#xff0c;有什么工具或技术可以帮助我们解决这个问题呢&#xff1f; 答案就是Eureka。 一、Eureka简介 Eureka是Netflix公司开源的…...

python程序设计基础:字符串与正则表达式

第四章&#xff1a;字符串与正则表达式 4.1字符串 最早的字符串编码是美国标准信息交换码ASCII&#xff0c;仅对10个数字、26个大写英文字母、26个小写英文字母及一些其他符号进行了编码。ASCII码采用1个字节来对字符进行编码&#xff0c;最多只能表示256个符号。 随着信息技…...

华为配置WDS手拉手业务示例

配置WDS手拉手业务示例 组网图形 图1 配置WDS手拉手业务示例组网图 业务需求组网需求数据规划配置思路配置注意事项操作步骤配置文件 业务需求 企业用户通过WLAN接入网络&#xff0c;以满足移动办公的最基本需求。但企业考虑到AP通过有线部署的成本较高&#xff0c;所以通过建立…...

Apache celeborn 安装及使用教程

1.下载安装包 https://celeborn.apache.org/download/ 测0.4.0时出现https://github.com/apache/incubator-celeborn/issues/835 2.解压 tar -xzvf apache-celeborn-0.3.2-incubating-bin.tgz 3.修改配置文件 cp celeborn-env.sh.template celeborn-env.shcp log4j2.xml.…...

数据保护:如何有效应对.BecSec-P-XXXXXXXX勒索病毒的威胁

导言&#xff1a; 随着网络安全威胁的不断增加&#xff0c;勒索软件成为了网络犯罪分子的一种常见手段之一。.BecSec-P-XXXXXXXX勒索病毒&#xff08;简称.BecSec勒索病毒&#xff09;作为其中之一&#xff0c;对用户的数据安全构成了严重威胁。本文91数据恢复将介绍.BecSec勒…...

流畅的Python(十二)-继承的优缺点

一、核心要义 1. 子类化内置类型的缺点 2.多重继承和方法解析顺序 二、代码示例 1. 子类化内置类型的缺点 #!/usr/bin/env python # -*- coding: utf-8 -*- # Time : 2024/2/24 7:29 # Author : Maple # File : 01-子类化内置类型的问题.py # Software: PyCharm fr…...

机器学习基础(三)监督学习的进阶探索

导语&#xff1a;上一节我们深入地探讨监督学习和非监督学习的知识&#xff0c;重点关注它们的理论基础、常用算法及实际应用场景&#xff0c;详情可见&#xff1a; 机器学习基础&#xff08;二&#xff09;监督与非监督学习-CSDN博客文章浏览阅读769次&#xff0c;点赞15次&a…...

avidemux-一个免费的视频编辑器,用于剪切、过滤和编码项目

avidemux-一个免费的视频编辑器&#xff0c;用于剪切、过滤和编码项目 avidemux-一个免费的视频编辑器&#xff0c;用于剪切、过滤和编码项目avidemux下载avidemux源代码参考资料 avidemux-一个免费的视频编辑器&#xff0c;用于剪切、过滤和编码项目 avidemux下载 avidemux …...

RisingWave最佳实践-利用Dynamic filters 和 Temporal filters 实现监控告警

心得的体会 刚过了年刚开工&#xff0c;闲暇之余调研了分布式SQL流处理数据库–RisingWave&#xff0c;本人是Flink&#xff08;包括FlinkSQL和Flink DataStream API&#xff09;的资深用户&#xff0c;但接触到RisingWave令我眼前一亮&#xff0c;并且拿我们生产上的监控告警…...

AtCoder 第409​场初级竞赛 A~E题解

A Conflict 【题目链接】 原题链接&#xff1a;A - Conflict 【考点】 枚举 【题目大意】 找到是否有两人都想要的物品。 【解析】 遍历两端字符串&#xff0c;只有在同时为 o 时输出 Yes 并结束程序&#xff0c;否则输出 No。 【难度】 GESP三级 【代码参考】 #i…...

最新SpringBoot+SpringCloud+Nacos微服务框架分享

文章目录 前言一、服务规划二、架构核心1.cloud的pom2.gateway的异常handler3.gateway的filter4、admin的pom5、admin的登录核心 三、code-helper分享总结 前言 最近有个活蛮赶的&#xff0c;根据Excel列的需求预估的工时直接打骨折&#xff0c;不要问我为什么&#xff0c;主要…...

屋顶变身“发电站” ,中天合创屋面分布式光伏发电项目顺利并网!

5月28日&#xff0c;中天合创屋面分布式光伏发电项目顺利并网发电&#xff0c;该项目位于内蒙古自治区鄂尔多斯市乌审旗&#xff0c;项目利用中天合创聚乙烯、聚丙烯仓库屋面作为场地建设光伏电站&#xff0c;总装机容量为9.96MWp。 项目投运后&#xff0c;每年可节约标煤3670…...

【Go】3、Go语言进阶与依赖管理

前言 本系列文章参考自稀土掘金上的 【字节内部课】公开课&#xff0c;做自我学习总结整理。 Go语言并发编程 Go语言原生支持并发编程&#xff0c;它的核心机制是 Goroutine 协程、Channel 通道&#xff0c;并基于CSP&#xff08;Communicating Sequential Processes&#xff0…...

数据链路层的主要功能是什么

数据链路层&#xff08;OSI模型第2层&#xff09;的核心功能是在相邻网络节点&#xff08;如交换机、主机&#xff09;间提供可靠的数据帧传输服务&#xff0c;主要职责包括&#xff1a; &#x1f511; 核心功能详解&#xff1a; 帧封装与解封装 封装&#xff1a; 将网络层下发…...

12.找到字符串中所有字母异位词

&#x1f9e0; 题目解析 题目描述&#xff1a; 给定两个字符串 s 和 p&#xff0c;找出 s 中所有 p 的字母异位词的起始索引。 返回的答案以数组形式表示。 字母异位词定义&#xff1a; 若两个字符串包含的字符种类和出现次数完全相同&#xff0c;顺序无所谓&#xff0c;则互为…...

【OSG学习笔记】Day 16: 骨骼动画与蒙皮(osgAnimation)

骨骼动画基础 骨骼动画是 3D 计算机图形中常用的技术&#xff0c;它通过以下两个主要组件实现角色动画。 骨骼系统 (Skeleton)&#xff1a;由层级结构的骨头组成&#xff0c;类似于人体骨骼蒙皮 (Mesh Skinning)&#xff1a;将模型网格顶点绑定到骨骼上&#xff0c;使骨骼移动…...

AI,如何重构理解、匹配与决策?

AI 时代&#xff0c;我们如何理解消费&#xff1f; 作者&#xff5c;王彬 封面&#xff5c;Unplash 人们通过信息理解世界。 曾几何时&#xff0c;PC 与移动互联网重塑了人们的购物路径&#xff1a;信息变得唾手可得&#xff0c;商品决策变得高度依赖内容。 但 AI 时代的来…...

蓝桥杯 冶炼金属

原题目链接 &#x1f527; 冶炼金属转换率推测题解 &#x1f4dc; 原题描述 小蓝有一个神奇的炉子用于将普通金属 O O O 冶炼成为一种特殊金属 X X X。这个炉子有一个属性叫转换率 V V V&#xff0c;是一个正整数&#xff0c;表示每 V V V 个普通金属 O O O 可以冶炼出 …...

佰力博科技与您探讨热释电测量的几种方法

热释电的测量主要涉及热释电系数的测定&#xff0c;这是表征热释电材料性能的重要参数。热释电系数的测量方法主要包括静态法、动态法和积分电荷法。其中&#xff0c;积分电荷法最为常用&#xff0c;其原理是通过测量在电容器上积累的热释电电荷&#xff0c;从而确定热释电系数…...