spring的aop_Spring AOP 小结

a4a923dac439b03b5f199b3ca55a04f9.png

1. AOP专业概述

在软件行业,AOP为Aspect Oriented Programming的缩写,意思为:面向切面编程,通过预编译方法和运行期动态代理实现程序功能的统一维护的一种技术。

要理解切面变成,就需要先理解什么是切面。用刀把一个西瓜分成两瓣,切开的切口就是切面;炒菜,锅与炉子共同来完成炒菜,锅与炉子就是切面。web层级设计中,web层->网关层->服务层->数据层,每一层之间也是一个切面。编程中,对象与对象之间,方法与方法之间,模块与模块之间都是一个个切面。

在实际工程中,我们一般做活动的时候,一般对每一个接口都会做活动的有效性校验(是否开始、是否结束等等)、以及这个接口是不是需要用户登录。按照正常的逻辑我们可以这么做:

155b294891fa7d55863e7185a4a53901.png

但是这样做有个问题:有多少接口,就要多少次代码的copy。

c07a07ae032c27b0c70f246be5ad278a.png

上图,提出一个公共的方法,每个接口都来调用这个接口。

bccc84b968cebef11d068cd51afd9dc7.png

每个接口总得要调用这个方法,于是就有了切面的概念,我将方法注入到接口调用的某个地方(切点)。

2. AOP中的相关概念

  1. Aspect(切面): Aspect 声明类似于 Java 中的类声明,在 Aspect 中会包含着一些 Pointcut 以及相应的 Advice。
  2. Joint point(连接点):表示在程序中明确定义的点,典型的包括方法调用,对类成员的访问以及异常处理程序块的执行等等,它自身还可以嵌套其它 joint point。
  3. Pointcut(切点):表示一组 joint point,这些 joint point 或是通过逻辑关系组合起来,或是通过通配、正则表达式等方式集中起来,它定义了相应的 Advice 将要发生的地方。
  4. Advice(增强):Advice 定义了在 Pointcut 里面定义的程序点具体要做的操作,它通过 before、after 和 around 来区别是在每个 joint point 之前、之后还是代替执行的代码。
  5. Target(目标对象):织入 Advice 的目标对象。
  6. Weaving(织入):将 Aspect 和其他对象连接起来, 并创建 Adviced object 的过程。

列举一个比较容易理解的例子:

从前有一个叫爪哇的小县城,在一个月黑风高的晚上。这个县城中发生了命案,作案的凶手十分狡猾,现场没有留下什么有价值的线索。不过万幸的是, 刚从隔壁回来的老王恰好在这时候无意中发现了凶手行凶的过程,但是由于天色已晚,加上凶手蒙着面,老王并没有看清凶手的面目,只知道凶手是个男性,身高约七尺五寸。爪哇县的县令根据老王的描述,对守门的士兵下命令说: 凡是发现有身高七尺五寸的男性,都要抓过来审问。士兵当然不敢违背县令的命令,只好把进出城的所有符合条件的人都抓了起来。

首先我们知道,在 Spring AOP 中 Joint point 指代的是所有方法的执行点, 而 point cut 是一个描述信息,它修饰的是 Joint point,通过 point cut,我们就可以确定哪些 Joint point 可以被织入 Advice。对应到我们在上面举的例子,我们可以做一个简单的类比,Joint point 就相当于 爪哇的小县城里的百姓,pointcut 就相当于老王所做的指控,即凶手是个男性,身高约七尺五寸,而 Advice 则是施加在符合老王所描述的嫌疑人的动作:抓过来审问。

  • Joint point : 爪哇的小县城里的百姓: 因为根据定义, Joint point 是所有可能被织入 Advice 的候选的点, 在 Spring AOP中, 则可以认为所有方法执行点都是 Joint point. 而在我们上面的例子中, 命案发生在小县城中, 按理说在此县城中的所有人都有可能是嫌疑人.
  • Pointcut :男性, 身高约七尺五寸: 我们知道, 所有的方法(joint point) 都可以织入 Advice, 但是我们并不希望在所有方法上都织入 Advice, 而 Pointcut 的作用就是提供一组规则来匹配joinpoint, 给满足规则的 joinpoint 添加 Advice. 同理, 对于县令来说, 他再昏庸, 也知道不能把县城中的所有百姓都抓起来审问, 而是根据凶手是个男性, 身高约七尺五寸, 把符合条件的人抓起来. 在这里 凶手是个男性, 身高约七尺五寸 就是一个修饰谓语, 它限定了凶手的范围, 满足此修饰规则的百姓都是嫌疑人, 都需要抓起来审问.
  • Advice :抓过来审问, Advice 是一个动作, 即一段 Java 代码, 这段 Java 代码是作用于 point cut 所限定的那些 Joint point 上的. 同理, 对比到我们的例子中, 抓过来审问 这个动作就是对作用于那些满足 男性, 身高约七尺五寸 的爪哇的小县城里的百姓.
  • Aspect::Aspect 是 point cut 与 Advice 的组合, 因此在这里我们就可以类比: “根据老王的线索, 凡是发现有身高七尺五寸的男性, 都要抓过来审问” 这一整个动作可以被认为是一个 Aspect.

3. Spring AOP实现原理

代理模式:(UML图如下)

7b89c3f4d0cd6078e415c2b2409efba8.png

代理类实现了被代理类的接口,同时与被代理类是组合的关系。

静态代理:

// 接口类:
interface Person{void speak();
}// 真实实体类
class Actor implements Person{private String content;public Actor(String content){this.content = content;}@Overridepublic void speak() {System.out.println(this.content);}
}//代理类
class Agent implements Person{private Actor actor;private String before;private String after;public Agent(Actor actor, String before, String after){this.actor = actor;this.before = before;this.after = after;}@Overridepublic void speak(){//before speakSystem.out.println("Before actor speak, Agent say: " + before);//real speakthis.actor.speak();//after speakSystem.out.println("After actor speak, Agent say: " + after);} 
}

动态代理

首先是java.lang.reflect包里面的InvocationHandler接口:

public interface InvocationHandler{public Object invoke(Object proxy, Method method, Object[] args)throws Throwable;
}

我们对于被代理的类的操作都会由该接口中的invoke()方法来实现,其中的参数的含义是:

  • proxy:被代理的类的实例;
  • method:调用被代理类的方法;
  • args:该方法需要的参数;

使用方法首先是需要实现该接口,并且我们可以在invoke方法中调用被代理类的方法并获得返回值,自然也可以在调用该方法的前后去做一些额外的事情,从而实现动态代理,

另外一个很重要的静态方法是java.lang.reflect包中的Proxy类的newProxyInstance方法:

public static Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h)throws IllegalArgumentException

其中参数含义如下:
loader:被代理的类的类加载器;
inferfaces:被代理类的接口数组;
invocationHandler:就是刚刚介绍的调用处理器类的对象实例;
该方法会返回一个被修改过的实例,从而可以自由的调用该实例的方法。

// Fruit接口
public interface Fruit{public void show();
}//Apple实现Fruit接口:
public class Apple implements Fruit{@Overridepublic void show() {System.out.println("<<<<show method is invoked");}
}//代理类Agent.java
public class DynamicAgent{// 实现InvocationHandler接口,并且可以初始化被代理类的对象static class MyHandler implements InvocationHandler{private Object proxy;public MyHandler(Object proxy){this.proxy = proxy;}// 自定义invoke方法@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable{System.out.println(">>>>>>>>>>before invoking");// 真正调用方法的地方Object ret = method.invoke(this.proxy, args);System.out.println(">>>>>>>>>>after invoking");return ret;}//返回一个被修改过的对象public static Object agent(Class interfaceClazz, Object proxy){return Proxy.newProxyInstance(interfaceClazz.getClassLoader(), new Class[]{interfaceClazz}, new MyHandler(proxy));}}
}public class ReflectTest {public static void main(String[] args) throws InvocationTargetException, IllegalAccessException {//注意一定要返回接口,不能返回实现类否则会报错Fruit fruit = (Fruit) DynamicAgent.agent(Fruit.class, new Apple());fruit.show();}
}

可以看到对于不同的实现类,可以用同一个动态代理类来进行代理,实现了“一次编写到处代理”的效果,但是这种方法有个缺点,就是被代理的类一定要实现了某个接口。

CGLIB库的方法:

CGLib是一个字节码增强库,为AOP等提供了底层的支持。它的实现方式如下:

import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;public class CGlibAgent implements MethodInterceptor {private Object proxy;public Object getInstance(Object proxy) {this.proxy = proxy;Enhancer enhancer = new Enhancer();enhancer.setSuperclass(this.proxy.getClass());// 回调方法enhancer.setCallback(this);// 创建代理对象return enhancer.create();}//回调方法@Overridepublic Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {System.out.println(">>>>before invoking");//真正调用Object ret = methodProxy.invokeSuper(o, objects);System.out.println(">>>>after invoking");return ret;}public static void main(String[] args) {CGlibAgent cGlibAgent = new CGlibAgent();Apple apple = (Apple) cGlibAgent.getInstance(new Apple());apple.show();}
}// 运行结果:
// before invoking
// show method is invoked
// after invoking

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/489761.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【解析】工业机器人中的各类传感器技术应用

来源&#xff1a;中国机器人网前言工业机器人涉及到的传感器有哪些&#xff1f;2012年&#xff0c;美国提出“工业互联网”&#xff0c;2013年&#xff0c;德国提出“工业4.0”&#xff0c;2015年&#xff0c;中国提出“中国制造2025”。在工业物联网、AR、云计算等技术热潮下&…

java水果超市mysql_Java基础 | 项目实战之水果超市

传智播客线上平台博学谷启动项目实战&#xff0c;在学习过程中真正还原企业实际开发流程及团队配合&#xff0c;同时对所学知识最大化吸收项目启动准备01规定学习位置参加项目实战&#xff0c;学习位置不能小于当前标注的位置02项目分组本次Java基础参加项目实战的同学较多&…

android dp sp px_Android屏幕适配★★重点盘点★★

引言屏幕适配是 android 开发/面试 绕不开的一个问题。本文 将屏幕适配的知识要点完整展现给各位读者。正文大纲android需要做屏幕适配的原因基础知识点(★★★很重要★★★)屏幕适配攻略正文↓↓↓android需要做屏幕适配的原因关键字&#xff1a;android碎片化android面世以来…

AI与网络安全的未来:数据集与协同能力

来源&#xff1a;安全牛有关 AI 优势与风险的争论如今已成媒体日常&#xff0c;很多此类讨论都集中在潜在负面影响上&#xff0c;话题范围从工作自动化导致广泛失业到 AI 用于创建 “深度伪造” 视频。但另一方面&#xff0c;我们已经在享受 AI 自动化助手的正面效果所带来的种…

ucinet计算聚类系数大于1怎么办_聚类性能评估-ARI(调兰德指数)

注意&#xff1a;ARI取值范围为[-1,1]&#xff0c;值越大越好&#xff0c;反映两种划分的重叠程度&#xff0c;使用该度量指标需要数据本身有类别标记。用C表示实际的类别划分&#xff0c;K表示聚类结果。定义a 为在C中被划分为同一类&#xff0c;在K中被划分为同一簇的实例对数…

这才是未来真正的风口,一文看清13种硬科技投资趋势

来源&#xff1a;资本实验室如果非要说“风口”&#xff0c;那么在未来10年乃至20年&#xff0c;硬科技就是最大的风口。近期&#xff0c;由麻省理工学院创建的非盈利投资机构The Engine与投资研究机构Pitchbook联合发布了一份名为《2019硬科技图景》的研究报告。该报告将硬科技…

mysql 滚屏查看查询结果_MySQL_查询操作(select)

查询操作1、别名查询select id 序号,name名字from test_1209ryc;2、条件查询(between)select * from test_1209ryc where id between 2 and 5;3、条件查询(in)select * from test_1209ryc where id in(1,2,3);4、子查询select * from test_1209ryc where id in (select id from…

new arraylist内存_如何避免内部类中的内存泄漏

我先假设读者已经熟悉在Java代码中使用嵌套类的基础知识。在本文里&#xff0c;我将展示嵌套类的陷阱&#xff0c;内部类在JVM中引起内存泄漏和内存不足错误的地方。之所以会发生这种类型的内存泄漏&#xff0c;是因为内部类必须始终能够访问其外部类。从简单的嵌套过程到内存不…

马斯克:“星链”卫星已能提供服务

来源&#xff1a;一财网美国太空探索技术公司首席执行官埃隆马斯克22日称&#xff0c;该公司发射的“星链”卫星已能提供天基互联网服务。马斯克当天在社交媒体推特上发布的一条推文中说&#xff0c;“正在通过‘星链’卫星发送这条推文”。2分钟后&#xff0c;他发推文表示&am…

sqlplus连mysql库_sqlplus连接数据库

sqlplus连接到远程数据库我一直以为sqlplus是服务器端的软件&#xff0c;今天我才知道sqlplus是客户端软件&#xff0c;用sqlplus也能连接到远程数据库。windows下具体连接方法如下&#xff1a;如果已经配置过tnsname方法一.在运行或者命令窗口里面先输入sqlplus/n...文章张振磊…

OpenGL ES入门

OpenGL ES渲染管线概述 渲染管线一般是由显示芯片GPU内部处理图形信号的并行处理单元组成&#xff0c;这些并行处理单元之间是独立的&#xff0c;从另一个角度看&#xff0c;渲染管线实际上也是一系列绘制过程&#xff0c;这一系列过程的输入是待绘制物体的相关描述信息&#x…

【前沿】MIT搞了个进取型机器人!能研究学习对象操纵的基础

来源&#xff1a;中国机器人网 前言&#xff1a;MIT的研究让数据有了机器人的方向麻省理工学院的研究人员已经汇编了一个数据集&#xff0c;该数据集捕获了物理上推动数百个不同对象的机器人系统的详细行为。研究人员可以使用数据集&#xff08;同类中规模最大&#xff0c;种类…

java进度条_自学java你需要知道的,适合编程小白

1. java学习网站之前在很多学习网站上学习过Java&#xff0c;踩过很多坑&#xff0c;今天给大家推荐一个比较好用的Java学习网站&#xff0c;希望大家能少踩坑Java教程 | 项目实践一站式java学习这个网站的针对性强&#xff0c;如果你是想学习Java&#xff0c;在这个网站学习就…

软考考前冲刺第一章计算机硬件基础知识

1.原码表示法和补码表示法是计算机中用于表示数据的两种编码方法&#xff0c;在计算机系统中常采用补码来表示和运算数据&#xff0c;原因是采用补码可以简化计算机运算部件的设计。 在计算机中&#xff0c;各类运算都可以采用补码进行&#xff0c;特别是对于有符号数的运算。在…

既然使用神经网络也可以解决分类问题,那SVM、决策树这些算法还有什么意义呢?...

来源&#xff1a;Jerry的算法和NLPJerry的算法和NLP先说下结论&#xff1a;没有一个模型是万能的&#xff0c;需要根据数据选择适合的模型。在机器学习中&#xff0c;数据大概可以分成四大类&#xff1a;图像 (Image)&#xff0c;序列(Sequence)&#xff0c;图(Graph) 和表格(T…

使用python处理子域名爆破工具subdomainsbrute结果txt

近期学习了一段时间python&#xff0c;结合自己的安全从业经验&#xff0c;越来越感觉到安全测试是一个体力活。如果没有良好的coding能力去自动化的话&#xff0c;无疑会把安全测试效率变得很低。 作为安全测试而言&#xff0c;第一步往往要通过爆破目标站的一级域名开始。作为…

美陆军将在2020年军演中测试人工智能新应用

▲美陆军利用人工智能技术探测隐藏的目标&#xff0c;例如这辆伪装的M109A6自行榴弹炮来源&#xff1a; 美国《防务快讯》/图片来自互联网 编者按美陆军人工智能工作组负责人表示&#xff0c;陆军已开发出可检测“侦察照片”中隐藏目标的人工智能技术&#xff0c;并将在明年举行…

Nature:1000种植物的测序揭示10亿年来的进化

来源&#xff1a;生物通千种植物转录组计划&#xff08;1,000 Plants Project&#xff0c;1KP&#xff09;是由加拿大科学家在2008年11月发起的&#xff0c;召集了将近200名植物学家对1,100多种植物的基因进行测序和分析。如今&#xff0c;这个项目的研究成果发表在《Nature》杂…

java 通过反射得到命名空间_利用反射得到一个命名空间下的所有类,并调用?...

当年话下Assembly.LoadFrom("assemblyName").GetTypes();Assembly.Load("assemblyName").GetTypes();遍历&#xff0c; 再通过Type.GetInterface(""),如果结果不为null&#xff0c;那就说明找到了再Activator.CreateInstance(“”)即可还是写段代…

量子霸权之争

来源&#xff1a; 原理这一个月以来&#xff0c;量子计算机领域吸引了许多人的关注&#xff0c;因为关于谷歌已经实现了人们期待已久的里程碑——“量子霸权”&#xff08;也被称为”量子优越性“&#xff09;的消息不胫而走。“量子霸权”是加州理工学院的理论物理学家John Pr…