
SpringBoot启动过程深度解析——Spring-Aop代理过程解析-jdk动态代理-cglib动态代理解析
发布日期:2023-09-20 01:38:40
浏览次数:1
分类:技术文章
本文共 28063 字,大约阅读时间需要 93 分钟。
SpringBoot启动过程深度解析——Spring-Aop代理过程解析-jdk动态代理-cglib动态代理解析
前言
讲述SpringAop代理过程前,需要提前理解AOP所使用的两种动态代理的原理,因此本文会用实际案例来阐述jdk和cglib两种动态代理的原理
jdk和cglib动态代理的区别
jdk动态代理逻辑 & 代码
被代理的接口
public interface Calculator { public int add(int i, int j); public int sub(int i, int j); public int mult(int i, int j); public int div(int i, int j);}
被代理的接口实现类
public class MyCalculator implements Calculator { public int add(int i, int j) { int result = i + j; return result; } public int sub(int i, int j) { int result = i - j; return result; } public int mult(int i, int j) { int result = i * j; return result; } public int div(int i, int j) { int result = i / j; return result; }}
创建JDK代理类,执行代理方法
记得开启保存JDK产生代理对象的class文件,以便于观察代理对象的执行逻辑代理对象class文件存储于项目下com/sun/proxy/$Proxy0.classSystem.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");
public class Test { public static void main(String[] args) { //开启保存JDK产生代理对象的class文件 System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true"); //创建被代理对象 MyCalculator myCalculator = new MyCalculator(); //获取类加载器 ClassLoader loader = myCalculator.getClass().getClassLoader(); //获取被代理对象所有接口 Class [] interfaces = myCalculator.getClass().getInterfaces(); //创建增强方法处理器对象 InvocationHandler invocationHandler = new InvocationHandler() { public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { try { Object result = null; try { //前置织入...可以做一些事 //通过反射执行原类的原方法 result = method.invoke(myCalculator, args); //后置织入...可以做一些事 } catch (Exception e) { //异常织入...可以做一些事 } return result; } finally { //返回织入...可以做一些事 } } }; //使用JDK代理创建代理对象 (需传入 类加载器、所有接口、增强方法处理器) Calculator proxy = (Calculator) Proxy.newProxyInstance(loader, interfaces, invocationHandler); //通过JDK代理对象进行方法调用,最终会调用invocationHandler的invoke方法进行增强 proxy.add(1,1); System.out.println(proxy.getClass()); }}
JDK产生的代理class文件
package com.sun.proxy;import com.test.proxy.jdk.Calculator;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;import java.lang.reflect.Proxy;import java.lang.reflect.UndeclaredThrowableException;public final class $Proxy0 extends Proxy implements Calculator { //此处都是通过反射得到的原对象的方法对象 private static Method m1; private static Method m2; private static Method m3; private static Method m5; private static Method m4; private static Method m6; private static Method m0; //反射得到的原对象的方法对象 static { try { m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object")); m2 = Class.forName("java.lang.Object").getMethod("toString"); m3 = Class.forName("com.test.proxy.jdk.Calculator").getMethod("add", Integer.TYPE, Integer.TYPE); m5 = Class.forName("com.test.proxy.jdk.Calculator").getMethod("sub", Integer.TYPE, Integer.TYPE); m4 = Class.forName("com.test.proxy.jdk.Calculator").getMethod("mult", Integer.TYPE, Integer.TYPE); m6 = Class.forName("com.test.proxy.jdk.Calculator").getMethod("div", Integer.TYPE, Integer.TYPE); m0 = Class.forName("java.lang.Object").getMethod("hashCode"); } catch (NoSuchMethodException var2) { throw new NoSuchMethodError(var2.getMessage()); } catch (ClassNotFoundException var3) { throw new NoClassDefFoundError(var3.getMessage()); } } //JDK代理类的构造需要传入 自定义的方法增强处理器 InvocationHandler public $Proxy0(InvocationHandler var1) throws { super(var1); } /** --------------------以下方法都是原对象同名同参的方法-------------------- **/ public final boolean equals(Object var1) throws { try { //通过自定义的方法增强处理器InvocationHandler 进行方法调用 return (Boolean)super.h.invoke(this, m1, new Object[]{ var1}); } catch (RuntimeException | Error var3) { throw var3; } catch (Throwable var4) { throw new UndeclaredThrowableException(var4); } } public final String toString() throws { try { //通过自定义的方法增强处理器InvocationHandler 进行方法反射调用 InvocationHandler.invoke 最终调用 method.invoke return (String)super.h.invoke(this, m2, (Object[])null); } catch (RuntimeException | Error var2) { throw var2; } catch (Throwable var3) { throw new UndeclaredThrowableException(var3); } } public final int add(int var1, int var2) throws { try { //通过自定义的方法增强处理器InvocationHandler 进行方法反射调用 InvocationHandler.invoke 最终调用 method.invoke return (Integer)super.h.invoke(this, m3, new Object[]{ var1, var2}); } catch (RuntimeException | Error var4) { throw var4; } catch (Throwable var5) { throw new UndeclaredThrowableException(var5); } } public final int sub(int var1, int var2) throws { try { //通过自定义的方法增强处理器InvocationHandler 进行方法反射调用 InvocationHandler.invoke 最终调用 method.invoke return (Integer)super.h.invoke(this, m5, new Object[]{ var1, var2}); } catch (RuntimeException | Error var4) { throw var4; } catch (Throwable var5) { throw new UndeclaredThrowableException(var5); } } public final int mult(int var1, int var2) throws { try { //通过自定义的方法增强处理器InvocationHandler 进行方法反射调用 InvocationHandler.invoke 最终调用 method.invoke return (Integer)super.h.invoke(this, m4, new Object[]{ var1, var2}); } catch (RuntimeException | Error var4) { throw var4; } catch (Throwable var5) { throw new UndeclaredThrowableException(var5); } } public final int div(int var1, int var2) throws { try { //通过自定义的方法增强处理器InvocationHandler 进行方法反射调用 InvocationHandler.invoke 最终调用 method.invoke return (Integer)super.h.invoke(this, m6, new Object[]{ var1, var2}); } catch (RuntimeException | Error var4) { throw var4; } catch (Throwable var5) { throw new UndeclaredThrowableException(var5); } } public final int hashCode() throws { try { //通过自定义的方法增强处理器InvocationHandler 进行方法反射调用 InvocationHandler.invoke 最终调用 method.invoke return (Integer)super.h.invoke(this, m0, (Object[])null); } catch (RuntimeException | Error var2) { throw var2; } catch (Throwable var3) { throw new UndeclaredThrowableException(var3); } }}
jdk动态代理逻辑图
cglib动态代理逻辑 & 代码
被代理的类
public class MyCalculator { public int add(int i, int j) { int result = i + j; return result; } public int sub(int i, int j) { int result = i - j; return result; } public int mult(int i, int j) { int result = i * j; return result; } public int div(int i, int j) { int result = i / j; return result; }}
实现一个方法拦截器MethodInterceptor (增强方法的处理在此)
public class MyCglib implements MethodInterceptor { @Override public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable { //增强处理... //【非反射】执行代理对象的 原方法 //MethodProxy是被代理类的原方法 解析的FastClass相关的对象,可以通过此对象进行非反射的调用方法 Object o1 = methodProxy.invokeSuper(o, objects); //增强处理... return o1; }}
创建代理类,执行代理方法
记得开启动态代理创建的class文件存储到本地System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY,"D:\\");
public class MyTest { public static void main(String[] args) { //动态代理创建的class文件存储到本地 System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY,"D:\\"); //创建一个Enhancer Enhancer enhancer = new Enhancer(); //设置enhancer对象的父类【设置被代理的对象Class】 enhancer.setSuperclass(MyCalculator.class); //设置enhancer的回调对象【设置代理方法的增强器,MethodInterceptor实现类对象】 //此处可以设置多个方法拦截器,通过代理对象调用方法时,会按照设置的拦截器顺序执行 enhancer.setCallback(new MyCglib()); //创建Cglib代理对象 MyCalculator myCalculator = (MyCalculator) enhancer.create(); //通过代理对象调用目标方法 myCalculator.add(1,1); System.out.println(myCalculator.getClass()); }}
Cglib产生的代理class文件会有以下三个:
【代理对象】 1.MyCalculator$$EnhancerByCGLIB$$3ff25b35.class【原对象的FastClass文件】 2.MyCalculator$$FastClassByCGLIB$$2af85576.class【代理对象的FastClass文件】 3.MyCalculator$$EnhancerByCGLIB$$3ff25b35$$FastClassByCGLIB$$c56f475e.class什么时FastClass文件? 为一个对象A创建它的FastClass对象,这个FastClass对象相当于A的方法索引。 根据A的方法名生成并关联一个index、每个index对应A的一个方法。 后续只要根据这个index以及A的实例,就可以调用fastClass的invoke(instanceOfA, index, args)方法来快速的调用A的方法了。 实现了Java反射的“运行时动态调用指定类的方法”的功能,但是使用了不同的机制。
【代理对象】1.MyCalculatorCGLIB.class
public class MyCalculator$$EnhancerByCGLIB$$3ff25b35 extends MyCalculator implements Factory { private boolean CGLIB$BOUND; public static Object CGLIB$FACTORY_DATA; private static final ThreadLocal CGLIB$THREAD_CALLBACKS; //传入的增强处理器,也就是MethodInterceptor private static final Callback[] CGLIB$STATIC_CALLBACKS; //第一个传入的增强处理器,优先调用此MethodInterceptor private MethodInterceptor CGLIB$CALLBACK_0; private static Object CGLIB$CALLBACK_FILTER; //反射得到的 add方法,没什么用处. private static final Method CGLIB$add$0$Method; //add方法的MethodProxy //此MethodProxy包含 原对象的FastClass 和 代理对象的FastClass 和 原对象add方法对应的下标 和 代理对象add方法对应的下标 private static final MethodProxy CGLIB$add$0$Proxy; private static final Object[] CGLIB$emptyArgs; //反射得到的 sub方法,没什么用处. private static final Method CGLIB$sub$1$Method; //sub方法的MethodProxy //此MethodProxy包含 原对象的FastClass 和 代理对象的FastClass 和 原对象sub方法对应的下标 和 代理对象sub方法对应的下标 private static final MethodProxy CGLIB$sub$1$Proxy; //以下方法也是同理.... private static final Method CGLIB$mult$2$Method; private static final MethodProxy CGLIB$mult$2$Proxy; private static final Method CGLIB$div$3$Method; private static final MethodProxy CGLIB$div$3$Proxy; private static final Method CGLIB$equals$4$Method; private static final MethodProxy CGLIB$equals$4$Proxy; private static final Method CGLIB$toString$5$Method; private static final MethodProxy CGLIB$toString$5$Proxy; private static final Method CGLIB$hashCode$6$Method; private static final MethodProxy CGLIB$hashCode$6$Proxy; private static final Method CGLIB$clone$7$Method; private static final MethodProxy CGLIB$clone$7$Proxy; static void CGLIB$STATICHOOK1() { CGLIB$THREAD_CALLBACKS = new ThreadLocal(); CGLIB$emptyArgs = new Object[0]; Class var0 = Class.forName("com.test.proxy.cglib.MyCalculator$$EnhancerByCGLIB$$3ff25b35"); Class var1; //反射获取原对象的所有方法 Method[] var10000 = ReflectUtils.findMethods(new String[]{ "add", "(II)I", "sub", "(II)I", "mult", "(II)I", "div", "(II)I"}, (var1 = Class.forName("com.test.proxy.cglib.MyCalculator")).getDeclaredMethods()); //原对象add方法 CGLIB$add$0$Method = var10000[0]; //原对象add方法的MethodProxy对象包含原对象的FastClass 和代理对象的FastClass 和原对象add方法对应的下标 和代理对象add方法对应的下标 CGLIB$add$0$Proxy = MethodProxy.create(var1, var0, "(II)I", "add", "CGLIB$add$0"); //原对象sub方法 CGLIB$sub$1$Method = var10000[1]; //原对象sub方法的MethodProxy对象包含原对象的FastClass 和代理对象的FastClass 和原对象sub方法对应的下标 和代理对象sub方法对应的下标 CGLIB$sub$1$Proxy = MethodProxy.create(var1, var0, "(II)I", "sub", "CGLIB$sub$1"); CGLIB$mult$2$Method = var10000[2]; CGLIB$mult$2$Proxy = MethodProxy.create(var1, var0, "(II)I", "mult", "CGLIB$mult$2"); CGLIB$div$3$Method = var10000[3]; CGLIB$div$3$Proxy = MethodProxy.create(var1, var0, "(II)I", "div", "CGLIB$div$3"); //父类相关的反射方法对象.....以下同理 var10000 = ReflectUtils.findMethods(new String[]{ "equals", "(Ljava/lang/Object;)Z", "toString", "()Ljava/lang/String;", "hashCode", "()I", "clone", "()Ljava/lang/Object;"}, (var1 = Class.forName("java.lang.Object")).getDeclaredMethods()); CGLIB$equals$4$Method = var10000[0]; CGLIB$equals$4$Proxy = MethodProxy.create(var1, var0, "(Ljava/lang/Object;)Z", "equals", "CGLIB$equals$4"); CGLIB$toString$5$Method = var10000[1]; CGLIB$toString$5$Proxy = MethodProxy.create(var1, var0, "()Ljava/lang/String;", "toString", "CGLIB$toString$5"); CGLIB$hashCode$6$Method = var10000[2]; CGLIB$hashCode$6$Proxy = MethodProxy.create(var1, var0, "()I", "hashCode", "CGLIB$hashCode$6"); CGLIB$clone$7$Method = var10000[3]; CGLIB$clone$7$Proxy = MethodProxy.create(var1, var0, "()Ljava/lang/Object;", "clone", "CGLIB$clone$7"); } final int CGLIB$add$0(int var1, int var2) { return super.add(var1, var2); } //通过代理对象调用add方法,会执行此方法 public final int add(int var1, int var2) { //获取第一个方法拦截器 MethodInterceptor var10000 = this.CGLIB$CALLBACK_0; if (var10000 == null) { CGLIB$BIND_CALLBACKS(this); var10000 = this.CGLIB$CALLBACK_0; } if (var10000 != null) { //通过方法拦截器进行拦截调用 //调用上面的代码:public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) Object var3 = var10000.intercept(this, CGLIB$add$0$Method, new Object[]{ new Integer(var1), new Integer(var2)}, CGLIB$add$0$Proxy); return var3 == null ? 0 : ((Number)var3).intValue(); } else { //没有拦截器,直接调用原对象的原方法 return super.add(var1, var2); } }}
【原对象的FastClass文件】 2.MyCalculator-FastClassByCGLIB.class
public class MyCalculator$$FastClassByCGLIB$$2af85576 extends FastClass { public MyCalculator$$FastClassByCGLIB$$2af85576(Class var1) { super(var1); } //.... //.... //.... //调用原对象的方法,此处需要传入fastClass中对应的方法表下标 //【下面还有一个方法,就是获取fastClass中对应的方法表下标方法】 public Object invoke(int var1, Object var2, Object[] var3) throws InvocationTargetException { //var10000 就是原对象 MyCalculator var10000 = (MyCalculator)var2; int var10001 = var1; try { switch (var10001) { case 0: //直接调用原对象的原方法 return new Integer(var10000.add(((Number)var3[0]).intValue(), ((Number)var3[1]).intValue())); case 1: //直接调用原对象的原方法 return new Integer(var10000.sub(((Number)var3[0]).intValue(), ((Number)var3[1]).intValue())); case 2: //直接调用原对象的原方法 return new Integer(var10000.div(((Number)var3[0]).intValue(), ((Number)var3[1]).intValue())); case 3: //直接调用原对象的原方法 return new Integer(var10000.mult(((Number)var3[0]).intValue(), ((Number)var3[1]).intValue())); case 4: //直接调用原对象的原方法 return new Boolean(var10000.equals(var3[0])); case 5: //直接调用原对象的原方法 return var10000.toString(); case 6: //直接调用原对象的原方法 return new Integer(var10000.hashCode()); } } catch (Throwable var4) { throw new InvocationTargetException(var4); } throw new IllegalArgumentException("Cannot find matching method/constructor"); } //相当于FastClass的方法下标表 //相当于FastClass的方法下标表 //相当于FastClass的方法下标表 public int getIndex(Signature var1) { String var10000 = var1.toString(); switch (var10000.hashCode()) { case -2131682232: if (var10000.equals("sub(II)I")) { return 1; } break; case -1287932281: if (var10000.equals("add(II)I")) { return 0; } break; case -1267343528: if (var10000.equals("mult(II)I")) { return 3; } break; case 303407255: if (var10000.equals("div(II)I")) { return 2; } break; case 1826985398: if (var10000.equals("equals(Ljava/lang/Object;)Z")) { return 4; } break; case 1913648695: if (var10000.equals("toString()Ljava/lang/String;")) { return 5; } break; case 1984935277: if (var10000.equals("hashCode()I")) { return 6; } } return -1; } //.... //.... //....}
【代理对象的FastClass文件】 3.MyCalculator-EnhancerByCGLIB-FastClassByCGLIB.class
public class MyCalculator$$EnhancerByCGLIB$$3ff25b35$$FastClassByCGLIB$$c56f475e extends FastClass { public MyCalculator$$EnhancerByCGLIB$$3ff25b35$$FastClassByCGLIB$$c56f475e(Class var1) { super(var1); } //.... //.... //.... //调用代理对象的方法,此处需要传入fastClass中对应的方法表下标 //【下面还有一个方法,就是获取fastClass中对应的方法表下标方法】 public Object invoke(int var1, Object var2, Object[] var3) throws InvocationTargetException { MyCalculator..EnhancerByCGLIB..3ff25b35 var10000 = (MyCalculator..EnhancerByCGLIB..3ff25b35)var2; int var10001 = var1; try { switch (var10001) { case 0: //直接调用代理对象的add方法 return new Integer(var10000.add(((Number)var3[0]).intValue(), ((Number)var3[1]).intValue())); case 1: return new Boolean(var10000.equals(var3[0])); case 2: return var10000.toString(); case 3: return new Integer(var10000.hashCode()); case 4: return var10000.clone(); case 5: return var10000.newInstance((Callback[])var3[0]); case 6: return var10000.newInstance((Class[])var3[0], (Object[])var3[1], (Callback[])var3[2]); case 7: return var10000.newInstance((Callback)var3[0]); case 8: var10000.setCallback(((Number)var3[0]).intValue(), (Callback)var3[1]); return null; case 9: var10000.setCallbacks((Callback[])var3[0]); return null; case 10: return var10000.getCallbacks(); case 11: return var10000.getCallback(((Number)var3[0]).intValue()); case 12: 3ff25b35.CGLIB$SET_STATIC_CALLBACKS((Callback[])var3[0]); return null; case 13: 3ff25b35.CGLIB$SET_THREAD_CALLBACKS((Callback[])var3[0]); return null; case 14: return 3ff25b35.CGLIB$findMethodProxy((Signature)var3[0]); case 15: 3ff25b35.CGLIB$STATICHOOK1(); return null; case 16: //直接调用代理对象的sub方法 return new Integer(var10000.sub(((Number)var3[0]).intValue(), ((Number)var3[1]).intValue())); case 17: //直接调用代理对象的div方法 return new Integer(var10000.div(((Number)var3[0]).intValue(), ((Number)var3[1]).intValue())); case 18: //直接调用代理对象的mult方法 return new Integer(var10000.mult(((Number)var3[0]).intValue(), ((Number)var3[1]).intValue())); case 19: return new Integer(var10000.CGLIB$add$0(((Number)var3[0]).intValue(), ((Number)var3[1]).intValue())); case 20: return new Integer(var10000.CGLIB$mult$3(((Number)var3[0]).intValue(), ((Number)var3[1]).intValue())); case 21: return var10000.CGLIB$toString$5(); case 22: return new Integer(var10000.CGLIB$sub$1(((Number)var3[0]).intValue(), ((Number)var3[1]).intValue())); case 23: return new Boolean(var10000.CGLIB$equals$4(var3[0])); case 24: return new Integer(var10000.CGLIB$div$2(((Number)var3[0]).intValue(), ((Number)var3[1]).intValue())); case 25: return var10000.CGLIB$clone$7(); case 26: return new Integer(var10000.CGLIB$hashCode$6()); } } catch (Throwable var4) { throw new InvocationTargetException(var4); } throw new IllegalArgumentException("Cannot find matching method/constructor"); } //相当于FastClass的方法下标表 //相当于FastClass的方法下标表 //相当于FastClass的方法下标表 public int getIndex(Signature var1) { String var10000 = var1.toString(); switch (var10000.hashCode()) { case -2131682232: if (var10000.equals("sub(II)I")) { return 16; } break; case -1870561232: if (var10000.equals("CGLIB$findMethodProxy(Lorg/springframework/cglib/core/Signature;)Lorg/springframework/cglib/proxy/MethodProxy;")) { return 14; } break; case -1860420502: if (var10000.equals("CGLIB$clone$7()Ljava/lang/Object;")) { return 25; } break; case -1745842178: if (var10000.equals("setCallbacks([Lorg/springframework/cglib/proxy/Callback;)V")) { return 9; } break; case -1641413109: if (var10000.equals("newInstance([Lorg/springframework/cglib/proxy/Callback;)Ljava/lang/Object;")) { return 5; } break; case -1457535688: if (var10000.equals("CGLIB$STATICHOOK1()V")) { return 15; } break; case -1411753352: if (var10000.equals("CGLIB$hashCode$6()I")) { return 26; } break; case -1287932281: if (var10000.equals("add(II)I")) { return 0; } break; case -1267343528: if (var10000.equals("mult(II)I")) { return 18; } break; case -1034266769: if (var10000.equals("CGLIB$SET_STATIC_CALLBACKS([Lorg/springframework/cglib/proxy/Callback;)V")) { return 12; } break; case -1025895669: if (var10000.equals("CGLIB$SET_THREAD_CALLBACKS([Lorg/springframework/cglib/proxy/Callback;)V")) { return 13; } break; case -988317324: if (var10000.equals("newInstance([Ljava/lang/Class;[Ljava/lang/Object;[Lorg/springframework/cglib/proxy/Callback;)Ljava/lang/Object;")) { return 6; } break; case -984241474: if (var10000.equals("CGLIB$add$0(II)I")) { return 19; } break; case -945552506: if (var10000.equals("CGLIB$mult$3(II)I")) { return 20; } break; case -658046452: if (var10000.equals("CGLIB$div$2(II)I")) { return 24; } break; case -508378822: if (var10000.equals("clone()Ljava/lang/Object;")) { return 4; } break; case -50496290: if (var10000.equals("CGLIB$sub$1(II)I")) { return 22; } break; case 303407255: if (var10000.equals("div(II)I")) { return 17; } break; case 593200387: if (var10000.equals("CGLIB$equals$4(Ljava/lang/Object;)Z")) { return 23; } break; case 610042816: if (var10000.equals("newInstance(Lorg/springframework/cglib/proxy/Callback;)Ljava/lang/Object;")) { return 7; } break; case 1132856532: if (var10000.equals("getCallbacks()[Lorg/springframework/cglib/proxy/Callback;")) { return 10; } break; case 1246779367: if (var10000.equals("setCallback(ILorg/springframework/cglib/proxy/Callback;)V")) { return 8; } break; case 1364367423: if (var10000.equals("getCallback(I)Lorg/springframework/cglib/proxy/Callback;")) { return 11; } break; case 1826985398: if (var10000.equals("equals(Ljava/lang/Object;)Z")) { return 1; } break; case 1913648695: if (var10000.equals("toString()Ljava/lang/String;")) { return 2; } break; case 1940521675: if (var10000.equals("CGLIB$toString$5()Ljava/lang/String;")) { return 21; } break; case 1984935277: if (var10000.equals("hashCode()I")) { return 3; } } return -1; } //.... //.... //....}
cglib动态代理逻辑图
AOP概述
AOP:AspectOrientedProgramming面向切面编程OOP:ObjectOrientedProgramming面向对象编程面向切面编程: 基于OOP基础之上新的编程思想,OOP面向的主要对象是类,而AOP面向的主要对象是切面。 通俗点说的话就是在程序运行期间,将某段代码动态切入到指定方法的指定位置进行运行的这种编程方式。 在处理日志、安全管理、事务管理等方面有非常重要的作用。 AOP是Spring中重要的核心点,虽然IOC容器没有依赖AOP,但是AOP提供了非常强大的功能,用来对IOC做补充。核心概念 切面(Aspect): 切面可以有日志切面,事务切面。通过 @AspectJ 实现一个切面类 指关注点模块化,这个关注点可能会横切多个对象。事务管理是企业级Java应用中有关横切关注点的例子。 在SpringAOP中,切面可以使用通用类基于模式的方式(schema-basedapproach)或者在普通类中以`@Aspect`注解(@AspectJ注解方式)来实现。 连接点(Joinpoint): 在程序执行过程中某个特定的点,例如某个方法调用的时间点或者处理异常的时间点。 在SpringAOP中,一个连接点总是代表一个方法的执行。 -通知(Advice): 在切面的某个特定的连接点上执行的动作。通知有多种类型,包括“around”,“before”and“after”等等。 通知的类型将在后面的章节进行讨论。许多AOP框架,包括Spring在内,都是以拦截器做通知模型的,并维护着一个以连接点为中心的拦截器链。 -切点(Pointcut):(切点表达式) 匹配连接点的断言。通知和切点表达式相关联,并在满足这个切点的连接点上运行(例如,当执行某个特定名称的方法时)。 切点表达式如何和连接点匹配是AOP的核心:Spring默认使用AspectJ切点语义。 -引入(Introduction): 声明额外的方法或者某个类型的字段。Spring允许引入新的接口(以及一个对应的实现)到任何被通知的对象上。 例如,可以使用引入来使bean实现`IsModified`接口,以便简化缓存机制(在AspectJ社区,引入也被称为内部类型声明(inter))。 -目标对象(Targetobject): 被一个或者多个切面所通知的对象。也被称作被通知(advised)对象。 既然SpringAOP是通过运行时代理实现的,那么这个对象永远是一个被代理(proxied)的对象。 -AOP代理(AOPproxy): AOP框架创建的对象,用来实现切面契约(aspectcontract)(包括通知方法执行等功能)。 在Spring中,AOP代理可以是JDK动态代理 或CGLIB代理。 -织入(Weaving): 把切面连接到其它的应用程序类型或者对象上,并创建一个被被通知的对象的过程。 这个过程可以在编译时(例如使用AspectJ编译器)、类加载时或运行时中完成。Spring和其他纯JavaAOP框架一样,是在运行时完成织入的。 AOP实现原理 在spring容器中,如果有接口,那么会使用jdk自带的动态代理,如果没有接口,那么会使用cglib的动态代理。AOP的通知类型 -前置通知(Beforeadvice): 在连接点之前运行但无法阻止执行流程进入连接点的通知(除非它引发异常)。 -后置返回通知(Afterreturningadvice): 在连接点正常完成后执行的通知(例如,当方法没有抛出任何异常并正常返回时)。 -后置异常通知(Afterthrowingadvice): 在方法抛出异常退出时执行的通知。 -后置通知(总会执行)(After(finally)advice): 当连接点退出的时候执行的通知(无论是正常返回还是异常退出)。 -环绕通知(AroundAdvice): 环绕连接点的通知,例如方法调用。这是最强大的一种通知类型,。环绕通知可以在方法调用前后完成自定义的行为。 它可以选择是否继续执行连接点或直接返回自定义的返回值又或抛出异常将执行结束。AOP的应用场景 -日志管理 -权限认证 -安全检查 -事务控制多个切面运行的顺序 1、默认切面名称的字典顺序进行执行的 2、@Order注解来解决,数值越小,优先级越高
AOP代理过程概述
需要注意的一些情况: 同个类中的两个方法相互调用,想让AOP对两个方法都生效,就需要设置expose-proxy属性值为true自己扩展通知类型: 1.实现AspectJXXXAdvice,实现MethodInterceptor
转载地址:https://blog.csdn.net/weixin_39072857/article/details/130120599 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!
发表评论
最新留言
哈哈,博客排版真的漂亮呢~
[***.90.31.176]2023年09月17日 04时42分59秒
关于作者

喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!
推荐文章
【高数-2】多元函数最值
2019-03-07
Scala编程1|Scala编程环境配置
2019-03-07
scala编程_2|scala变量声明与for循环
2019-03-07
【Scala编程_3】|数组
2019-03-07
【Scala编程_4】IDEA快捷键
2019-03-07
【Scala编程_5】map
2019-03-07
【Scala编程_8】方法与函数
2019-03-07
【Java】List集合常用创建方式
2019-03-07
【Java】String字符串的比较
2019-03-07
基于Spark rdd的单词计数,Java与Scala版本
2019-03-07
由GeoJson格式渲染地图
2019-03-07
Spark集群启动与查看Spark集群进程启动情况
2019-03-07
浮点数精度问题——由Mathf.Floor()引发的思考
2019-03-07
Unity——浅谈AB包(AssetBundle)
2019-03-07
Mac、移动端的抓包方式和注意事项——Charles
2019-03-07
Unity资源管理和策略
2019-03-07
番茄工作法——总结笔记
2019-03-07
Redux 源码共读 -- 1
2019-03-07
使用 nodeJs 实现 js/ts 文件翻译功能
2019-03-07