您好,登錄后才能下訂單哦!
本篇內(nèi)容主要講解“Spring中AOP的概念和JDK動態(tài)代理的實現(xiàn)方式”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學習“Spring中AOP的概念和JDK動態(tài)代理的實現(xiàn)方式”吧!
AOP的概念
AOP:Aspect-Oriented Programming(面向切面編程),維基百科的解釋如下:Aspect是一種新的模塊化機制,用來描述分散在對象、類或者函數(shù)中的橫切關注點,從關注點中分離出橫切關注點是面向切面的程序設計的核心概念。分離關注點使解決特定領域問題的代碼從業(yè)務邏輯中獨立出來,業(yè)務邏輯的代碼中不在含有針對特定領域問題的代碼的調(diào)用,業(yè)務邏輯同特定領域問題的關系通過切面來封裝、維護,這樣原本分散在整個應用程序中的變動就可以很好地管理起來。從AOP的角度,應用可以分為橫切關注點和業(yè)務邏輯代碼,實際開發(fā)中,這些橫切關注點往往會直接嵌入到業(yè)務邏輯代碼中,面向切面編程就是要解決把橫切關注點與業(yè)務邏輯相分離
實現(xiàn)方式:
Spring默認使用 JDK 動態(tài)代理作為AOP的代理,缺陷是目標類的類必須實現(xiàn)接口,否則不能使用JDK動態(tài)代理。如果需要代理的是類而不是接口,那么Spring會默認使用CGLIB代理,關于兩者的區(qū)別:jdk動態(tài)代理是通過java的反射機制來實現(xiàn)的,目標類必須要實現(xiàn)接口,cglib是針對類來實現(xiàn)代理的,他的原理是動態(tài)的為指定的目標類生成一個子類,并覆蓋其中方法實現(xiàn)增強,但因為采用的是繼承,所以不能對final修飾的類進行代理。
JDK動態(tài)代理
Jdk動態(tài)代理是在程序運行過程中,根據(jù)目標類實現(xiàn)的接口來動態(tài)生成代理類的class文件,使用主要涉及兩個類:
InvocationHandler接口: 它提供了一個invoke(Object obj,Method method, Object[] args)
方法供實現(xiàn)者提供相應的代理邏輯的實現(xiàn)。可以對實際的實現(xiàn)進行一些特殊的處理其中參數(shù)
Object obj :被代理的目標類
Method method: 需要執(zhí)行的目標類的方法
Object[] args :目標方法的參數(shù)
Proxy類:提供一個方法newProxyInstance (ClassLoader loader, Class[] interfaces, InvocationHandler h)
來獲得動態(tài)代理類
示例代碼:
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(),//代理類已實現(xiàn)的接口 this); //動態(tài)代理調(diào)用方法是關聯(lián)的InvocationHandler,最終通過此InvocationHandler的invoke方法執(zhí)行真正的方法 } //實現(xiàn)相應的代理邏輯 @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方法在哪里調(diào)用的?我們看一下JDK源碼:看看DK動態(tài)代理的過程是什么樣的:
根據(jù)源碼內(nèi)部的函數(shù)調(diào)用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<Object, Supplier<V>> valuesMap = map.get(cacheKey); if (valuesMap == null) { ConcurrentMap<Object, Supplier<V>> oldValuesMap = map.putIfAbsent(cacheKey, valuesMap = new ConcurrentHashMap<>()); if (oldValuesMap != null) { valuesMap = oldValuesMap; } } // create subKey and retrieve the possible Supplier<V> stored by that // subKey from valuesMap Object subKey = Objects.requireNonNull(subKeyFactory.apply(key, parameter)); Supplier<V> supplier = valuesMap.get(subKey); Factory factory = null; while (true) { if (supplier != null) { // supplier might be a Factory or a CacheValue<V> instance V value = supplier.get(); if (value != null) { return value; } } // else no supplier in cache // or a supplier that returned null (could be a cleared CacheValue // or a Factory that wasn't successful in installing the CacheValue) // lazily construct a Factory if (factory == null) { factory = new Factory(key, parameter, subKey, valuesMap); } if (supplier == null) { supplier = valuesMap.putIfAbsent(subKey, factory); if (supplier == null) { // successfully installed Factory supplier = factory; } // else retry with winning supplier } else { if (valuesMap.replace(subKey, supplier, factory)) { // successfully replaced // cleared CacheEntry / unsuccessful Factory // with our Factory supplier = factory; } else { // retry with current supplier supplier = valuesMap.get(subKey); } } } }
可以看到函數(shù)return value; 而 V value = supplier.get();
繼續(xù)往下讀可以發(fā)現(xiàn) supper=factory,實際上是一個Factory對象,那么繼續(xù)查看Factory.get()
方法
public synchronized V get() { // serialize access // re-check Supplier<V> supplier = 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<V> 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(BiFunction<K, P, ?> subKeyFactory, BiFunction<K, P, V> valueFactory) { this.subKeyFactory = Objects.requireNonNull(subKeyFactory); this.valueFactory = Objects.requireNonNull(valueFactory); } private static final WeakCache<ClassLoader, Class<?>[], Class<?>> proxyClassCache = new WeakCache<>(new KeyFactory(), new ProxyClassFactory());
可以知道valueFactory是ProxyClassFactory類型對象,直接查看ProxyClassFactory. Apply()
方法
public Class<?> apply(ClassLoader loader, Class<?>[] interfaces) { Map<Class<?>, 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);
調(diào)用ProxyGenerator.generateProxyClass
最終動態(tài)生成一個代理類,但是似乎并未找到何處調(diào)用了invoke方法;參考CSDN: https://www.jb51.net/article/118935.htm這篇文章,嘗試將這個動態(tài)生成的二進制字節(jié)碼輸出到本地,并反編譯出來一看究竟,測試代碼如下:
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(); //輸出動態(tài)代理類字節(jié)碼 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文件反編譯查看:
具體動態(tài)代理類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); } }
實際上動態(tài)代理類繼承自Proxy,并且實現(xiàn)了目標類繼承的接口,在createOrder方法中調(diào)用了invoke方法,實現(xiàn)了切面邏輯的植入,這里也回答了一個問題,為什么JDK動態(tài)代理的目標類必須是實現(xiàn)接口的,因為代理類其實是針對接口代理,而不是針對類來代理的,動態(tài)代理類自己繼承自Proxy,Java也不允許多重繼承。動態(tài)代理類和目標類其實是各自實現(xiàn)了接口,代理類通過InvocationHandler.invoke實現(xiàn)對目標類方法的調(diào)用。
CGLIB動態(tài)代理
CGLIB代理是通過使用一個字節(jié)碼處理框架ASM,來轉換字節(jié)碼并生成新的類,并在子類中采用方法攔截的技術攔截所有父類方法的調(diào)用,實現(xiàn)織如如橫切邏輯 ,效率上比使用反射技術的JDK動態(tài)代理要高,但是由于CGLIB的原理是動態(tài)為目標類生成子類代理類,所以不能為聲明為final的方法進行代理。其使用主要涉及兩個類:
MethodInterceptor接口:該接口提供一個方法intercept(Object arg0, Method arg1, Object[] arg2, MethodProxy arg3)
主要用于攔截目標類方法的調(diào)用
Object arg0, :被代理的目標類
Method arg1, 委托方法
Object[] arg2, 方法參數(shù)
MethodProxy arg3 :代理方法的MethodProxy對象
Enhancer類:用于創(chuàng)建代理類
示例:
實現(xiàn)MethodInterceptor接口,代理類在調(diào)用方法時,CGLIB會回調(diào)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; } /** * 創(chuàng)建代理對象 * */ public Object getInstance() { Enhancer enhancer = new Enhancer(); //設置目標類(需要被代理的類) enhancer.setSuperclass(this.targetClass.getClass()); // 回調(diào)方法 enhancer.setCallback(this); // 創(chuàng)建代理對象 return enhancer.create(); } /** * 攔截所有目標類方法的調(diào)用 * */ @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); //通過生成子類的方式創(chuàng)建代理類 OrderServiceImpl proxyImp = (OrderServiceImpl)proxy.getInstance(); proxyImp.createOrder(); }
結果:
System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "D:\\class");
將cglib動態(tài)代理類輸出到指定目錄,反編譯查看一下代理類真面目:
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.<init>(); 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并且實現(xiàn)了接口Factory,代理類中關于createorder生成了兩個方法CGLIB$createOrder$0和createOrder:
CGLIB$createOrder$0方法內(nèi)部直接調(diào)用目標類的supper.createOrder
createOrder方法內(nèi)部首先盤點否實現(xiàn)了MethodInterceptor接口的callback,如果存在則調(diào)用MethodInterceptor接口攔截方法intercept,根據(jù)前面的實現(xiàn)intercept方法內(nèi)部實現(xiàn)了對目標方法的調(diào)用Object o1 = arg3.invokeSuper(arg0, arg2)
,invokeSuper內(nèi)部實際上是直接調(diào)用的代理類的CGLIB$createOrder$0()
方法,最終調(diào)用了目標類createOrder。
兩種代理對比
JDK動態(tài)代理:
代理類與委托類實現(xiàn)同一接口,主要是通過代理類實現(xiàn)InvocationHandler并重寫invoke方法來進行動態(tài)代理的,在invoke方法中將對方法進行增強處理 優(yōu)點:不需要硬編碼接口,代碼復用率高,缺點:只能夠代理實現(xiàn)了接口的委托類
CGLIB動態(tài)代理:
代理類將委托類作為自己的父類并為其中的非final委托方法創(chuàng)建兩個方法,一個是與委托方法簽名相同的方法,它在方法中會通過super調(diào)用委托方法;另一個是代理類獨有的方法。在代理方法中,它會判斷是否存在實現(xiàn)了MethodInterceptor接口的對象,若存在則將調(diào)用intercept方法對委托方法進行代理 優(yōu)點:可以在運行時對類或者是接口進行增強操作,且委托類無需實現(xiàn)接口,缺點:不能對final類以及final方法進行代理
到此,相信大家對“Spring中AOP的概念和JDK動態(tài)代理的實現(xiàn)方式”有了更深的了解,不妨來實際操作一番吧!這里是億速云網(wǎng)站,更多相關內(nèi)容可以進入相關頻道進行查詢,關注我們,繼續(xù)學習!
免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權內(nèi)容。