十年网站开发经验 + 多家企业客户 + 靠谱的建站团队
量身定制 + 运营维护+专业推广+无忧售后,网站问题一站解决
本篇内容主要讲解“Spring中AOP的概念和JDK动态代理的实现方式”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Spring中AOP的概念和JDK动态代理的实现方式”吧!
网站建设哪家好,找创新互联公司!专注于网页设计、网站建设、微信开发、小程序设计、集团企业网站建设等服务项目。为回馈新老客户创新互联还提供了兰考免费建站欢迎大家使用!
AOP的概念
AOP:Aspect-Oriented Programming(面向切面编程),维基百科的解释如下:Aspect是一种新的模块化机制,用来描述分散在对象、类或者函数中的横切关注点,从关注点中分离出横切关注点是面向切面的程序设计的核心概念。分离关注点使解决特定领域问题的代码从业务逻辑中独立出来,业务逻辑的代码中不在含有针对特定领域问题的代码的调用,业务逻辑同特定领域问题的关系通过切面来封装、维护,这样原本分散在整个应用程序中的变动就可以很好地管理起来。从AOP的角度,应用可以分为横切关注点和业务逻辑代码,实际开发中,这些横切关注点往往会直接嵌入到业务逻辑代码中,面向切面编程就是要解决把横切关注点与业务逻辑相分离
实现方式:
Spring默认使用 JDK 动态代理作为AOP的代理,缺陷是目标类的类必须实现接口,否则不能使用JDK动态代理。如果需要代理的是类而不是接口,那么Spring会默认使用CGLIB代理,关于两者的区别:jdk动态代理是通过java的反射机制来实现的,目标类必须要实现接口,cglib是针对类来实现代理的,他的原理是动态的为指定的目标类生成一个子类,并覆盖其中方法实现增强,但因为采用的是继承,所以不能对final修饰的类进行代理。
JDK动态代理
Jdk动态代理是在程序运行过程中,根据目标类实现的接口来动态生成代理类的class文件,使用主要涉及两个类:
InvocationHandler接口: 它提供了一个invoke(Object obj,Method method, Object[] args)
方法供实现者提供相应的代理逻辑的实现。可以对实际的实现进行一些特殊的处理其中参数
Object obj :被代理的目标类
Method method: 需要执行的目标类的方法
Object[] args :目标方法的参数
Proxy类:提供一个方法newProxyInstance (ClassLoader loader, Class[] interfaces, InvocationHandler h)
来获得动态代理类
示例代码:
public interface OrderService { public void createOrder(); }
public class OrderServiceImpl implements OrderService { @Override public void createOrder() { System.out.println("creating order"); } }
public class OrderLogger { public void beforeCreateOrder(){ System.out.println("before create order"); } public void afterCreateOrder(){ System.out.println("after create order"); } }
package com.sl.aop; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; public class ServiceProxy implements InvocationHandler { private Object targetClass; private OrderLogger orderLogger; public ServiceProxy(Object targetClass,OrderLogger orderLogger) { this.targetClass = targetClass; this.orderLogger = orderLogger; } //获取代理 public Object GetDynamicProxy() { return Proxy.newProxyInstance(targetClass.getClass().getClassLoader(), //通过这个ClassLoader生成代理对象 targetClass.getClass().getInterfaces(),//代理类已实现的接口 this); //动态代理调用方法是关联的InvocationHandler,最终通过此InvocationHandler的invoke方法执行真正的方法 } //实现相应的代理逻辑 @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { this.orderLogger.beforeCreateOrder(); Object result= method.invoke(targetClass, args); this.orderLogger.afterCreateOrder(); return result; } }
测试类:
package com.sl.aop; import org.junit.Test; public class AopTest { @Test public void Testdynamicproxy() { OrderServiceImpl serviceImpl = new OrderServiceImpl(); OrderLogger logger = new OrderLogger(); OrderService service = (OrderService) new ServiceProxy(serviceImpl, logger).GetDynamicProxy(); service.createOrder(); } }
运行结果:
到这个其实还是有点困惑,Proxy.newProxyInstance()
这个返回的是什么? Invoke方法在哪里调用的?我们看一下JDK源码:看看DK动态代理的过程是什么样的:
根据源码内部的函数调用Proxy.newProxyInstance()->Proxy.getProxyClass0()->WeakCache.get()
,先定位到
WeakCache.class:
public V get(K key, P parameter) { Objects.requireNonNull(parameter); expungeStaleEntries(); Object cacheKey = CacheKey.valueOf(key, refQueue); // lazily install the 2nd level valuesMap for the particular cacheKey ConcurrentMap
可以看到函数return value; 而 V value = supplier.get();
继续往下读可以发现 supper=factory,实际上是一个Factory对象,那么继续查看Factory.get()
方法
public synchronized V get() { // serialize access // re-check Suppliersupplier = valuesMap.get(subKey); if (supplier != this) { // something changed while we were waiting: // might be that we were replaced by a CacheValue // or were removed because of failure -> // return null to signal WeakCache.get() to retry // the loop return null; } // else still us (supplier == this) // create new value V value = null; try { value = Objects.requireNonNull(valueFactory.apply(key, parameter)); } finally { if (value == null) { // remove us on failure valuesMap.remove(subKey, this); } } // the only path to reach here is with non-null value assert value != null; // wrap value with CacheValue (WeakReference) CacheValue cacheValue = new CacheValue<>(value); // try replacing us with CacheValue (this should always succeed) if (valuesMap.replace(subKey, this, cacheValue)) { // put also in reverseMap reverseMap.put(cacheValue, Boolean.TRUE); } else { throw new AssertionError("Should not reach here"); } // successfully replaced us with new CacheValue -> return the value // wrapped by it return value; }
Return value;那么直接查看赋值语句:value = Objects.requireNonNull(valueFactory.apply(key, parameter));
valueFactory又什么鬼?
public WeakCache(BiFunctionsubKeyFactory, BiFunction valueFactory) { this.subKeyFactory = Objects.requireNonNull(subKeyFactory); this.valueFactory = Objects.requireNonNull(valueFactory); } private static final WeakCache [], Class>> proxyClassCache = new WeakCache<>(new KeyFactory(), new ProxyClassFactory());
可以知道valueFactory是ProxyClassFactory类型对象,直接查看ProxyClassFactory. Apply()
方法
public Class> apply(ClassLoader loader, Class>[] interfaces) { Map, Boolean> interfaceSet = new IdentityHashMap<>(interfaces.length); for (Class> intf : interfaces) { /* * Verify that the class loader resolves the name of this * interface to the same Class object. */ Class> interfaceClass = null; try { interfaceClass = Class.forName(intf.getName(), false, loader); } catch (ClassNotFoundException e) { } if (interfaceClass != intf) { throw new IllegalArgumentException( intf + " is not visible from class loader"); } /* * Verify that the Class object actually represents an * interface. */ if (!interfaceClass.isInterface()) { throw new IllegalArgumentException( interfaceClass.getName() + " is not an interface"); } /* * Verify that this interface is not a duplicate. */ if (interfaceSet.put(interfaceClass, Boolean.TRUE) != null) { throw new IllegalArgumentException( "repeated interface: " + interfaceClass.getName()); } } String proxyPkg = null; // package to define proxy class in int accessFlags = Modifier.PUBLIC | Modifier.FINAL; /* * Record the package of a non-public proxy interface so that the * proxy class will be defined in the same package. Verify that * all non-public proxy interfaces are in the same package. */ for (Class> intf : interfaces) { int flags = intf.getModifiers(); if (!Modifier.isPublic(flags)) { accessFlags = Modifier.FINAL; String name = intf.getName(); int n = name.lastIndexOf('.'); String pkg = ((n == -1) ? "" : name.substring(0, n + 1)); if (proxyPkg == null) { proxyPkg = pkg; } else if (!pkg.equals(proxyPkg)) { throw new IllegalArgumentException( "non-public interfaces from different packages"); } } } if (proxyPkg == null) { // if no non-public proxy interfaces, use com.sun.proxy package proxyPkg = ReflectUtil.PROXY_PACKAGE + "."; } /* * Choose a name for the proxy class to generate. */ long num = nextUniqueNumber.getAndIncrement(); String proxyName = proxyPkg + proxyClassNamePrefix + num; /* * Generate the specified proxy class. */ byte[] proxyClassFile = ProxyGenerator.generateProxyClass( proxyName, interfaces, accessFlags); try { return defineClass0(loader, proxyName, proxyClassFile, 0, proxyClassFile.length); } catch (ClassFormatError e) { /* * A ClassFormatError here means that (barring bugs in the * proxy class generation code) there was some other * invalid aspect of the arguments supplied to the proxy * class creation (such as virtual machine limitations * exceeded). */ throw new IllegalArgumentException(e.toString()); } } }
直接画重点:
byte[] proxyClassFile = ProxyGenerator.generateProxyClass( proxyName, interfaces, accessFlags); return defineClass0(loader, proxyName, proxyClassFile, 0, proxyClassFile.length);
调用ProxyGenerator.generateProxyClass
最终动态生成一个代理类,但是似乎并未找到何处调用了invoke方法;参考CSDN: https://www.jb51.net/article/118935.htm这篇文章,尝试将这个动态生成的二进制字节码输出到本地,并反编译出来一看究竟,测试代码如下:
public class AopTest { @Test public void Testdynamicproxy() { OrderServiceImpl serviceImpl = new OrderServiceImpl(); OrderLogger logger = new OrderLogger(); OrderService service = (OrderService) new ServiceProxy(serviceImpl, logger).GetDynamicProxy(); service.createOrder(); //输出动态代理类字节码 createProxyClassFile(); } private static void createProxyClassFile(){ String name = "ProxyObject"; byte[] data = ProxyGenerator.generateProxyClass(name,new Class[]{OrderService.class}); FileOutputStream out =null; try { out = new FileOutputStream(name+".class"); System.out.println((new File("hello")).getAbsolutePath()); out.write(data); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); }finally { if(null!=out) try { out.close(); } catch (IOException e) { e.printStackTrace(); } } } }
使用java Decompiler工具将这个二进制class文件反编译查看:
具体动态代理类ProxyObject.java:
import com.sl.aop.OrderService; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.lang.reflect.UndeclaredThrowableException; public final class ProxyObject extends Proxy implements OrderService { private static Method m1; private static Method m2; private static Method m3; private static Method m0; public ProxyObject(InvocationHandler paramInvocationHandler) { super(paramInvocationHandler); } public final boolean equals(Object paramObject) { try { return ((Boolean)this.h.invoke(this, m1, new Object[] { paramObject })).booleanValue(); } catch (Error|RuntimeException localError) { throw localError; } catch (Throwable localThrowable) { throw new UndeclaredThrowableException(localThrowable); } } public final String toString() { try { return (String)this.h.invoke(this, m2, null); } catch (Error|RuntimeException localError) { throw localError; } catch (Throwable localThrowable) { throw new UndeclaredThrowableException(localThrowable); } } public final void createOrder() { try { this.h.invoke(this, m3, null); return; } catch (Error|RuntimeException localError) { throw localError; } catch (Throwable localThrowable) { throw new UndeclaredThrowableException(localThrowable); } } public final int hashCode() { try { return ((Integer)this.h.invoke(this, m0, null)).intValue(); } catch (Error|RuntimeException localError) { throw localError; } catch (Throwable localThrowable) { throw new UndeclaredThrowableException(localThrowable); } } static { try { m1 = Class.forName("java.lang.Object").getMethod("equals", new Class[] { Class.forName("java.lang.Object") }); m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]); m3 = Class.forName("com.sl.aop.OrderService").getMethod("createOrder", new Class[0]); m0 = Class.forName("java.lang.Object").getMethod("hashCode", new Class[0]); return; } catch (NoSuchMethodException localNoSuchMethodException) { throw new NoSuchMethodError(localNoSuchMethodException.getMessage()); } catch (ClassNotFoundException localClassNotFoundException) { throw new NoClassDefFoundError(localClassNotFoundException.getMessage()); } }
终于看到关于invoke的部分了:
public final void createOrder() { try { this.h.invoke(this, m3, null); return; } catch (Error|RuntimeException localError) { throw localError; } catch (Throwable localThrowable) { throw new UndeclaredThrowableException(localThrowable); } }
实际上动态代理类继承自Proxy,并且实现了目标类继承的接口,在createOrder方法中调用了invoke方法,实现了切面逻辑的植入,这里也回答了一个问题,为什么JDK动态代理的目标类必须是实现接口的,因为代理类其实是针对接口代理,而不是针对类来代理的,动态代理类自己继承自Proxy,Java也不允许多重继承。动态代理类和目标类其实是各自实现了接口,代理类通过InvocationHandler.invoke实现对目标类方法的调用。
CGLIB动态代理
CGLIB代理是通过使用一个字节码处理框架ASM,来转换字节码并生成新的类,并在子类中采用方法拦截的技术拦截所有父类方法的调用,实现织如如横切逻辑 ,效率上比使用反射技术的JDK动态代理要高,但是由于CGLIB的原理是动态为目标类生成子类代理类,所以不能为声明为final的方法进行代理。其使用主要涉及两个类:
MethodInterceptor接口:该接口提供一个方法intercept(Object arg0, Method arg1, Object[] arg2, MethodProxy arg3)
主要用于拦截目标类方法的调用
Object arg0, :被代理的目标类
Method arg1, 委托方法
Object[] arg2, 方法参数
MethodProxy arg3 :代理方法的MethodProxy对象
Enhancer类:用于创建代理类
示例:
实现MethodInterceptor接口,代理类在调用方法时,CGLIB会回调MethodInterceptor接口intercept方法,从而织入切面逻辑。
package com.sl.aop; import java.lang.reflect.Method; import org.springframework.cglib.proxy.Enhancer; import org.springframework.cglib.proxy.MethodInterceptor; import org.springframework.cglib.proxy.MethodProxy; public class CglibServiceProxy implements MethodInterceptor { private Object targetClass; private OrderLogger orderLogger; public CglibServiceProxy(Object targetClass,OrderLogger orderLogger) { this.targetClass = targetClass; this.orderLogger = orderLogger; } /** * 创建代理对象 * */ public Object getInstance() { Enhancer enhancer = new Enhancer(); //设置目标类(需要被代理的类) enhancer.setSuperclass(this.targetClass.getClass()); // 回调方法 enhancer.setCallback(this); // 创建代理对象 return enhancer.create(); } /** * 拦截所有目标类方法的调用 * */ @Override public Object intercept(Object arg0, Method arg1, Object[] arg2, MethodProxy arg3) throws Throwable { orderLogger.beforeCreateOrder(); Object o1 = arg3.invokeSuper(arg0, arg2); orderLogger.afterCreateOrder(); return o1; } }
测试方法:
public void Testdynamicproxy() { System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "D:\\class"); OrderServiceImpl serviceImpl = new OrderServiceImpl(); OrderLogger logger = new OrderLogger(); CglibServiceProxy proxy = new CglibServiceProxy(serviceImpl,logger); //通过生成子类的方式创建代理类 OrderServiceImpl proxyImp = (OrderServiceImpl)proxy.getInstance(); proxyImp.createOrder(); }
结果:
System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "D:\\class");
将cglib动态代理类输出到指定目录,反编译查看一下代理类真面目:
package com.sl.aop; import com.sl.aop.OrderServiceImpl; import java.lang.reflect.Method; import org.springframework.cglib.core.ReflectUtils; import org.springframework.cglib.core.Signature; import org.springframework.cglib.proxy.Callback; import org.springframework.cglib.proxy.Factory; import org.springframework.cglib.proxy.MethodInterceptor; import org.springframework.cglib.proxy.MethodProxy; public class OrderServiceImpl$$EnhancerByCGLIB$$17779aa4 extends OrderServiceImpl implements Factory { private boolean CGLIB$BOUND; public static Object CGLIB$FACTORY_DATA; private static final ThreadLocal CGLIB$THREAD_CALLBACKS; private static final Callback[] CGLIB$STATIC_CALLBACKS; private MethodInterceptor CGLIB$CALLBACK_0; private static Object CGLIB$CALLBACK_FILTER; private static final Method CGLIB$createOrder$0$Method; private static final MethodProxy CGLIB$createOrder$0$Proxy; private static final Object[] CGLIB$emptyArgs; private static final Method CGLIB$equals$1$Method; private static final MethodProxy CGLIB$equals$1$Proxy; private static final Method CGLIB$toString$2$Method; private static final MethodProxy CGLIB$toString$2$Proxy; private static final Method CGLIB$hashCode$3$Method; private static final MethodProxy CGLIB$hashCode$3$Proxy; private static final Method CGLIB$clone$4$Method; private static final MethodProxy CGLIB$clone$4$Proxy; static void CGLIB$STATICHOOK1() { CGLIB$THREAD_CALLBACKS = new ThreadLocal(); CGLIB$emptyArgs = new Object[0]; Class var0 = Class.forName("com.sl.aop.OrderServiceImpl$$EnhancerByCGLIB$$17779aa4"); Class var1; Method[] 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$1$Method = var10000[0]; CGLIB$equals$1$Proxy = MethodProxy.create(var1, var0, "(Ljava/lang/Object;)Z", "equals", "CGLIB$equals$1"); CGLIB$toString$2$Method = var10000[1]; CGLIB$toString$2$Proxy = MethodProxy.create(var1, var0, "()Ljava/lang/String;", "toString", "CGLIB$toString$2"); CGLIB$hashCode$3$Method = var10000[2]; CGLIB$hashCode$3$Proxy = MethodProxy.create(var1, var0, "()I", "hashCode", "CGLIB$hashCode$3"); CGLIB$clone$4$Method = var10000[3]; CGLIB$clone$4$Proxy = MethodProxy.create(var1, var0, "()Ljava/lang/Object;", "clone", "CGLIB$clone$4"); CGLIB$createOrder$0$Method = ReflectUtils.findMethods(new String[]{"createOrder", "()V"}, (var1 = Class.forName("com.sl.aop.OrderServiceImpl")).getDeclaredMethods())[0]; CGLIB$createOrder$0$Proxy = MethodProxy.create(var1, var0, "()V", "createOrder", "CGLIB$createOrder$0"); } final void CGLIB$createOrder$0() { super.createOrder(); } public final void createOrder() { MethodInterceptor var10000 = this.CGLIB$CALLBACK_0; if(this.CGLIB$CALLBACK_0 == null) { CGLIB$BIND_CALLBACKS(this); var10000 = this.CGLIB$CALLBACK_0; } if(var10000 != null) { var10000.intercept(this, CGLIB$createOrder$0$Method, CGLIB$emptyArgs, CGLIB$createOrder$0$Proxy); } else { super.createOrder(); } } final boolean CGLIB$equals$1(Object var1) { return super.equals(var1); } public final boolean equals(Object var1) { MethodInterceptor var10000 = this.CGLIB$CALLBACK_0; if(this.CGLIB$CALLBACK_0 == null) { CGLIB$BIND_CALLBACKS(this); var10000 = this.CGLIB$CALLBACK_0; } if(var10000 != null) { Object var2 = var10000.intercept(this, CGLIB$equals$1$Method, new Object[]{var1}, CGLIB$equals$1$Proxy); return var2 == null?false:((Boolean)var2).booleanValue(); } else { return super.equals(var1); } } final String CGLIB$toString$2() { return super.toString(); } public final String toString() { MethodInterceptor var10000 = this.CGLIB$CALLBACK_0; if(this.CGLIB$CALLBACK_0 == null) { CGLIB$BIND_CALLBACKS(this); var10000 = this.CGLIB$CALLBACK_0; } return var10000 != null?(String)var10000.intercept(this, CGLIB$toString$2$Method, CGLIB$emptyArgs, CGLIB$toString$2$Proxy):super.toString(); } final int CGLIB$hashCode$3() { return super.hashCode(); } public final int hashCode() { MethodInterceptor var10000 = this.CGLIB$CALLBACK_0; if(this.CGLIB$CALLBACK_0 == null) { CGLIB$BIND_CALLBACKS(this); var10000 = this.CGLIB$CALLBACK_0; } if(var10000 != null) { Object var1 = var10000.intercept(this, CGLIB$hashCode$3$Method, CGLIB$emptyArgs, CGLIB$hashCode$3$Proxy); return var1 == null?0:((Number)var1).intValue(); } else { return super.hashCode(); } } final Object CGLIB$clone$4() throws CloneNotSupportedException { return super.clone(); } protected final Object clone() throws CloneNotSupportedException { MethodInterceptor var10000 = this.CGLIB$CALLBACK_0; if(this.CGLIB$CALLBACK_0 == null) { CGLIB$BIND_CALLBACKS(this); var10000 = this.CGLIB$CALLBACK_0; } return var10000 != null?var10000.intercept(this, CGLIB$clone$4$Method, CGLIB$emptyArgs, CGLIB$clone$4$Proxy):super.clone(); } public static MethodProxy CGLIB$findMethodProxy(Signature var0) { String var10000 = var0.toString(); switch(var10000.hashCode()) { case -2138148221: if(var10000.equals("createOrder()V")) { return CGLIB$createOrder$0$Proxy; } break; case -508378822: if(var10000.equals("clone()Ljava/lang/Object;")) { return CGLIB$clone$4$Proxy; } break; case 1826985398: if(var10000.equals("equals(Ljava/lang/Object;)Z")) { return CGLIB$equals$1$Proxy; } break; case 1913648695: if(var10000.equals("toString()Ljava/lang/String;")) { return CGLIB$toString$2$Proxy; } break; case 1984935277: if(var10000.equals("hashCode()I")) { return CGLIB$hashCode$3$Proxy; } } return null; } public OrderServiceImpl$$EnhancerByCGLIB$$17779aa4() { CGLIB$BIND_CALLBACKS(this); } public static void CGLIB$SET_THREAD_CALLBACKS(Callback[] var0) { CGLIB$THREAD_CALLBACKS.set(var0); } public static void CGLIB$SET_STATIC_CALLBACKS(Callback[] var0) { CGLIB$STATIC_CALLBACKS = var0; } private static final void CGLIB$BIND_CALLBACKS(Object var0) { OrderServiceImpl$$EnhancerByCGLIB$$17779aa4 var1 = (OrderServiceImpl$$EnhancerByCGLIB$$17779aa4)var0; if(!var1.CGLIB$BOUND) { var1.CGLIB$BOUND = true; Object var10000 = CGLIB$THREAD_CALLBACKS.get(); if(var10000 == null) { var10000 = CGLIB$STATIC_CALLBACKS; if(CGLIB$STATIC_CALLBACKS == null) { return; } } var1.CGLIB$CALLBACK_0 = (MethodInterceptor)((Callback[])var10000)[0]; } } public Object newInstance(Callback[] var1) { CGLIB$SET_THREAD_CALLBACKS(var1); OrderServiceImpl$$EnhancerByCGLIB$$17779aa4 var10000 = new OrderServiceImpl$$EnhancerByCGLIB$$17779aa4(); CGLIB$SET_THREAD_CALLBACKS((Callback[])null); return var10000; } public Object newInstance(Callback var1) { CGLIB$SET_THREAD_CALLBACKS(new Callback[]{var1}); OrderServiceImpl$$EnhancerByCGLIB$$17779aa4 var10000 = new OrderServiceImpl$$EnhancerByCGLIB$$17779aa4(); CGLIB$SET_THREAD_CALLBACKS((Callback[])null); return var10000; } public Object newInstance(Class[] var1, Object[] var2, Callback[] var3) { CGLIB$SET_THREAD_CALLBACKS(var3); OrderServiceImpl$$EnhancerByCGLIB$$17779aa4 var10000 = new OrderServiceImpl$$EnhancerByCGLIB$$17779aa4; switch(var1.length) { case 0: var10000.(); CGLIB$SET_THREAD_CALLBACKS((Callback[])null); return var10000; default: throw new IllegalArgumentException("Constructor not found"); } } public Callback getCallback(int var1) { CGLIB$BIND_CALLBACKS(this); MethodInterceptor var10000; switch(var1) { case 0: var10000 = this.CGLIB$CALLBACK_0; break; default: var10000 = null; } return var10000; } public void setCallback(int var1, Callback var2) { switch(var1) { case 0: this.CGLIB$CALLBACK_0 = (MethodInterceptor)var2; default: } } public Callback[] getCallbacks() { CGLIB$BIND_CALLBACKS(this); return new Callback[]{this.CGLIB$CALLBACK_0}; } public void setCallbacks(Callback[] var1) { this.CGLIB$CALLBACK_0 = (MethodInterceptor)var1[0]; } static { CGLIB$STATICHOOK1(); } }
上面的代码可以看到代理类OrderServiceImpl$$EnhancerByCGLIB$$17779aa4 继承目标类OrderServiceImpl并且实现了接口Factory,代理类中关于createorder生成了两个方法CGLIB$createOrder$0和createOrder:
CGLIB$createOrder$0方法内部直接调用目标类的supper.createOrder
createOrder方法内部首先盘点否实现了MethodInterceptor接口的callback,如果存在则调用MethodInterceptor接口拦截方法intercept,根据前面的实现intercept方法内部实现了对目标方法的调用Object o1 = arg3.invokeSuper(arg0, arg2)
,invokeSuper内部实际上是直接调用的代理类的CGLIB$createOrder$0()
方法,最终调用了目标类createOrder。
两种代理对比
JDK动态代理:
代理类与委托类实现同一接口,主要是通过代理类实现InvocationHandler并重写invoke方法来进行动态代理的,在invoke方法中将对方法进行增强处理 优点:不需要硬编码接口,代码复用率高,缺点:只能够代理实现了接口的委托类
CGLIB动态代理:
代理类将委托类作为自己的父类并为其中的非final委托方法创建两个方法,一个是与委托方法签名相同的方法,它在方法中会通过super调用委托方法;另一个是代理类独有的方法。在代理方法中,它会判断是否存在实现了MethodInterceptor接口的对象,若存在则将调用intercept方法对委托方法进行代理 优点:可以在运行时对类或者是接口进行增强操作,且委托类无需实现接口,缺点:不能对final类以及final方法进行代理
到此,相信大家对“Spring中AOP的概念和JDK动态代理的实现方式”有了更深的了解,不妨来实际操作一番吧!这里是创新互联网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!