Spring底层原理(六)

news/2024/10/24 7:23:30/

Spring底层原理(六)

本章内容

介绍AOP的实现方式、JDK代理的模拟实现与源码

AOP的实现方式
  • 使用代理模式

    • jdk动态代理
    • cglib动态代理
  • 使用aspectj的编译器,该编译器会直接对字节码进行修改,可以实现静态方法增强

    在这里插入图片描述

  • 使用javaagent,在jvm option中指定-javaagent:aspectjweaver.jar,它会在字节码加载阶段对方法进行织入

JDK动态代理的模拟实现
public interface InvocationHandler {/*** @param proxy  代理对象* @param method 调用的方法* @param args   方法参数* @return       返回结果* @throws Throwable 运行异常*/Object invoke(Object proxy, Method method,Object[] args) throws Throwable;
}public interface Foo {int foo();void bar();
}
public class Obj {static class Target implements Foo {@Overridepublic int foo() {System.out.println("foo");return 100;}@Overridepublic void bar() {System.out.println("bar");}}public static void main(String[] args) {$Proxy0 proxy0 = new $Proxy0(new InvocationHandler() {@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Exception {System.out.println("before...");return method.invoke(new Target(),args);}});proxy0.bar();int foo = proxy0.foo();System.out.println(foo);}
}
public class $Proxy0 implements Foo {private InvocationHandler h;static Method foo;static Method bar;static {try {bar = Foo.class.getDeclaredMethod("bar");foo = Foo.class.getDeclaredMethod("foo");} catch (NoSuchMethodException e) {e.printStackTrace();}}public $Proxy0(InvocationHandler h) {this.h = h;}@Overridepublic int foo() {try {return (int) h.invoke(this, foo, new Object[0]) + 1;} catch (RuntimeException | Error e) {throw e;} catch (Throwable e) {//对于检查异常需要包装成RuntimeExceptionthrow new UndeclaredThrowableException(e);}}@Overridepublic void bar() {try {h.invoke(this, bar, new Object[0]);} catch (RuntimeException | Error e) {throw e;} catch (Throwable e) {//对于检查异常需要包装成RuntimeExceptionthrow new UndeclaredThrowableException(e);}}
}
JDK动态代理源码

在这里插入图片描述

在这里插入图片描述

JDK动态代理的优化
 public Object invoke(Object obj, Object... args)throws IllegalAccessException, IllegalArgumentException,InvocationTargetException{if (!override) {Class<?> caller = Reflection.getCallerClass();checkAccess(caller, clazz,Modifier.isStatic(modifiers) ? null : obj.getClass(),modifiers);}MethodAccessor ma = methodAccessor;             // read volatileif (ma == null) {ma = acquireMethodAccessor();}return ma.invoke(obj, args);}
  • 可以看到JDK反射的底层是使用了MethodAccessor的实现类
  • 实际上由于反射的效率低下,在循环反射16次后,直到第17次会使用GeneratedMethodAccessor创建一个代理对象出来直接调用方法,不再使用反射调用

在这里插入图片描述


http://www.ppmy.cn/news/1194641.html

相关文章

FANUC机器人PRIO-621和PRIO-622设备和控制器没有运行故障处理

FANUC机器人PRIO-621和PRIO-622设备和控制器没有运行故障处理 如下图所示&#xff0c;新的机器人开机后提示报警&#xff1a; PRIO-621 设备没有运行 PRIO-622 控制器没有运行 我们首先查看下手册上的报警代码说明&#xff0c;如下图所示&#xff0c; 如下图所示&#xff0c…

通过终端命令实现本地文件与远程Git仓库的上传与拉取!

​要将本地文件上传到Git仓库&#xff0c;需要遵循以下步骤&#xff1a; 初始化仓库&#xff08;如果尚未初始化&#xff09;&#xff1a; 导航到包含你的项目文件的文件夹&#xff0c;打开命令行(windows)或终端(git) git终端下载&#xff1a;Git的下载与安装教程_git下载安…

传智杯-21算法赛初赛B组题目详细解法解析-AB题(C/C++、Python、Java)

🚀 欢迎来到 ACM 算法题库专栏 🚀 在ACM算法题库专栏,热情推崇算法之美,精心整理了各类比赛题目的详细解法,包括但不限于ICPC、CCPC、蓝桥杯、LeetCode周赛、传智杯等等。无论您是刚刚踏入算法领域,还是经验丰富的竞赛选手,这里都是提升技能和知识的理想之地。 ✨ 经典…

MySQL中的空格处理

在处理数据库查询时&#xff0c;我们常常会遇到一些看似简单但实际上需要注意的细节。今天&#xff0c;我们将深入探讨MySQL中的空格处理&#xff0c;以及如何在Java中有效地处理这些问题。 1. MySQL中的空格 在MySQL中&#xff0c;空格是一个特殊的字符&#xff0c;其ASCII值…

华纳云:ubuntu系统如何建立软连接?

在Ubuntu中&#xff0c;您可以使用ln命令来创建软连接&#xff08;符号链接&#xff09;。软链接是指向另一个文件或目录的引用&#xff0c;类似于Windows中的快捷方式。创建软链接的语法如下&#xff1a; ln -s /path/to/source /path/to/link 其中&#xff1a; /path/to/s…

美颜SDK哪家便宜?企业级美颜工具包

在当今竞争激烈的企业宣传领域&#xff0c;一张优质的照片可以为企业带来巨大的价值。然而&#xff0c;由于各种原因&#xff0c;拍摄的照片、视频往往存在一些瑕疵&#xff0c;如肤色不均、背景杂乱等。为了解决这个问题&#xff0c;美摄科技特别推出了面向企业的专业美颜SDK&…

Python武器库开发-常用模块之copy模块(十五)

常用模块之copy模块(十五) 在Python编程中&#xff0c;我们经常遇到需要复制或拷贝数据的情况。为了避免不必要的问题和错误&#xff0c;Python提供了copy模块来处理复制操作。本文将介绍copy模块的用法&#xff0c;包括浅拷贝和深拷贝的概念以及如何在不同场景中使用。 我们…

Latex编辑记录

1 第一段默认是不首行缩进的 在最前面合适的地方&#xff0c;也即是有usepackage类似定义的地方粘贴下列语句 \usepackage{indentfirst} 然后在要首行缩进的地方&#xff0c;放下面这个语句即可 \setlength{\parindent}{2em} 2 公式编辑 3 对文本高亮标记 \usepackage{soul}…