具體有以下四步驟:html
建立業務接口java
public interface UserService { /** * 須要加強的方法 */ void add(); }
建立業務接口 實現類git
public class UserServiceImpl implements UserService { @Override public void add() { System.out.println("-------------業務邏輯方法 add ------------"); } }
建立自定義的 InvocationHandler,用於對接口提供的方法進行加強github
public class MyInvocationHandler implements InvocationHandler { /** * 須要加強的對象 */ private Object target; public MyInvocationHandler(Object target) { this.target = target; } /** * 執行目標對象 */ @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("-------------方法執行前的加強邏輯 ------------"); Object result = method.invoke(target, args); System.out.println("-------------方法執行後的加強邏輯 ------------"); return result; } public Object getProxy() { return Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(), target.getClass().getInterfaces(), this); } }
測試類spring
public class ProxyTest { @Test public void contextTest() { // 實例化目標對象 UserService userService = new UserServiceImpl(); // 實例化 InvocationHandler MyInvocationHandler invocationHandler = new MyInvocationHandler(userService); // 生成代理對象 UserService proxy = (UserService) invocationHandler.getProxy(); // 輸出代理類的class ProxySourceClassUtil.writeClassToDisk("C:\\Users\\yuhao.wang3\\Desktop\\" + proxy.getClass().getSimpleName() + ".class", proxy.getClass().getSimpleName(), UserService.class); // 調用代理對象的方法 proxy.add(); } }
輸出結果:app
Connected to the target VM, address: '127.0.0.1:60738', transport: 'socket' -------------方法執行前的加強邏輯 ------------ -------------業務邏輯方法 add ------------ -------------方法執行後的加強邏輯 ------------ Disconnected from the target VM, address: '127.0.0.1:60738', transport: 'socket'
用起來很簡單,其實’這基本上就 AOP 的一個簡單實現了,在目標對象的方法執行以前和 執行以後進行了加強。 Spring的AOP實現其實也是用了 Proxy 和 InvocationHandler。在整個建立過程當中InvocationHandler的建立最爲核心,在自定義的InvocationHandler中須要從新3個函數:less
package com.xiaolyuh.aop.jdk; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.lang.reflect.UndeclaredThrowableException; // 代理類會去實現咱們的接口 public final class Proxy4 extends Proxy implements UserService { // 解析全部的方法 private static Method m1; private static Method m2; private static Method m3; private static Method m0; public Proxy4() throws { super(paramInvocationHandler); } public final boolean equals() throws { try { return ((Boolean) this.h.invoke(this, m1, new Object[]{paramObject})).booleanValue(); } catch (RuntimeException localRuntimeException) { throw localRuntimeException; } catch (Throwable localThrowable) { throw new UndeclaredThrowableException(localThrowable); } } public final String toString() throws { try { return ((String) this.h.invoke(this, m2, null)); } catch (RuntimeException localRuntimeException) { throw localRuntimeException; } catch (Throwable localThrowable) { throw new UndeclaredThrowableException(localThrowable); } } public final void add() throws { try { // 經過InvocationHandler的invoke方法去執行加強和原有方法邏輯 this.h.invoke(this, m3, null); return; } catch (RuntimeException localRuntimeException) { throw localRuntimeException; } catch (Throwable localThrowable) { throw new UndeclaredThrowableException(localThrowable); } } public final int hashCode() throws { try { return ((Integer) this.h.invoke(this, m0, null)).intValue(); } catch (RuntimeException localRuntimeException) { throw localRuntimeException; } catch (Throwable localThrowable) { throw new UndeclaredThrowableException(localThrowable); } } static { try { // 解析全部的method出來 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.xiaolyuh.aop.jdk.UserService").getMethod("add", 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()); } } }
從結果咱們能夠看出,代理類會實現咱們的接口,並會實現咱們接口中的方法。而後經過InvocationHandler的invoke方法去執行加強邏輯和原有方法邏輯。在invoke中咱們可使用反射去執行原有邏輯,並在方法執行先後加上本身的加強邏輯。socket
JdkDynamicAopProxy是Spring中JDK動態代理的實現,它也實現了InvocationHandler接口。核心方法:ide
源碼:函數
final class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializable { ... /** Config used to configure this proxy(對加強器的支持) */ private final AdvisedSupport advised; ... public JdkDynamicAopProxy(AdvisedSupport config) throws AopConfigException { Assert.notNull(config, "AdvisedSupport must not be null"); if (config.getAdvisors().length == 0 && config.getTargetSource() == AdvisedSupport.EMPTY_TARGET_SOURCE) { throw new AopConfigException("No advisors and no TargetSource specified"); } this.advised = config; } @Override public Object getProxy() { return getProxy(ClassUtils.getDefaultClassLoader()); } @Override public Object getProxy(ClassLoader classLoader) { if (logger.isDebugEnabled()) { logger.debug("Creating JDK dynamic proxy: target source is " + this.advised.getTargetSource()); } // 獲取目標類接口 Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true); findDefinedEqualsAndHashCodeMethods(proxiedInterfaces); // 返回代理對象 return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this); } ... /** * Implementation of {@code InvocationHandler.invoke}. * <p>Callers will see exactly the exception thrown by the target, * unless a hook method throws an exception. */ @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { MethodInvocation invocation; Object oldProxy = null; boolean setProxyContext = false; TargetSource targetSource = this.advised.targetSource; Class<?> targetClass = null; Object target = null; try { // equals 方法處理 if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) { // The target does not implement the equals(Object) method itself. return equals(args[0]); } // hashCode 方法處理 else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) { // The target does not implement the hashCode() method itself. return hashCode(); } else if (method.getDeclaringClass() == DecoratingProxy.class) { // There is only getDecoratedClass() declared -> dispatch to proxy config. return AopProxyUtils.ultimateTargetClass(this.advised); } else if (!this.advised.opaque && method.getDeclaringClass().isInterface() && method.getDeclaringClass().isAssignableFrom(Advised.class)) { // Service invocations on ProxyConfig with the proxy config... return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args); } Object retVal; // 有時候目標對象內部的自我調用沒法實施切面中的加強則須要經過此屬性暴露代理 if (this.advised.exposeProxy) { // Make invocation available if necessary. oldProxy = AopContext.setCurrentProxy(proxy); setProxyContext = true; } // May be null. Get as late as possible to minimize the time we "own" the target, // in case it comes from a pool. target = targetSource.getTarget(); if (target != null) { targetClass = target.getClass(); } // 獲取當前方法的攔截鏈 List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass); if (chain.isEmpty()) { // 若是沒有攔截鏈那麼直接調用切點方法 Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args); retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse); } else { // 將攔截器封裝在ReflectiveMethodInvocation中,以便使用proceed方法執行攔截鏈 invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain); // 執行攔截鏈 retVal = invocation.proceed(); } // Massage return value if necessary. Class<?> returnType = method.getReturnType(); if (retVal != null && retVal == target && returnType != Object.class && returnType.isInstance(proxy) && !RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) { // Special case: it returned "this" and the return type of the method // is type-compatible. Note that we can't help if the target sets // a reference to itself in another returned object. retVal = proxy; } else if (retVal == null && returnType != Void.TYPE && returnType.isPrimitive()) { throw new AopInvocationException( "Null return value from advice does not match primitive return type for: " + method); } return retVal; } finally { if (target != null && !targetSource.isStatic()) { // Must have come from TargetSource. targetSource.releaseTarget(target); } if (setProxyContext) { // Restore old proxy. AopContext.setCurrentProxy(oldProxy); } } } ... }
cglib(Code Generation Library)是一個強大的,高性能,高質量的Code生成類庫。它能夠在運行期擴展Java類與實現Java接口。
須要代理的類
public class EnhancerDemo { public void test() { System.out.println("-------------業務邏輯方法 test ------------"); } }
MethodInterceptor的實現類(加強器)
import org.springframework.cglib.proxy.MethodInterceptor; import org.springframework.cglib.proxy.MethodProxy; import java.lang.reflect.Method; public class MethodInterceptorImpl implements MethodInterceptor { @Override public Object intercept(Object object, Method method, Object[] args, MethodProxy methodProxy) throws Throwable { System.out.println("-------------方法執行前的加強邏輯 ------------" + method); Object result = methodProxy.invokeSuper(object, args); System.out.println("-------------方法執行後的加強邏輯 ------------" + method); return result; } }
測試類:
public class EnhancerTest { @Test public void contextTest() { System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "D:\\class"); Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(EnhancerDemo.class); enhancer.setCallback(new MethodInterceptorImpl()); EnhancerDemo proxy = (EnhancerDemo) enhancer.create(); proxy.test(); System.out.println(proxy); } }
執行結果
Connected to the target VM, address: '127.0.0.1:61217', transport: 'socket' -------------方法執行前的加強邏輯 ------------public void com.xiaolyuh.aop.cglib.EnhancerDemo.test() -------------業務邏輯方法 test ------------ -------------方法執行後的加強邏輯 ------------public void com.xiaolyuh.aop.cglib.EnhancerDemo.test() -------------方法執行前的加強邏輯 ------------public java.lang.String java.lang.Object.toString() -------------方法執行前的加強邏輯 ------------public native int java.lang.Object.hashCode() -------------方法執行後的加強邏輯 ------------public native int java.lang.Object.hashCode() -------------方法執行後的加強邏輯 ------------public java.lang.String java.lang.Object.toString() com.xiaolyuh.aop.cglib.EnhancerDemo$$EnhancerByCGLIB$$da6c48f9@7a187f14 Disconnected from the target VM, address: '127.0.0.1:61217', transport: 'socket'
能夠看到 System.out.println(porxy); 首先調用了 toString() 方法,而後又調用了 hashCode() ,生成的對象爲 EnhancerDemo$$EnhancerByCGLIB$$da6c48f9@7a187f14
的實例,這個類是運行時由 CGLIB 產生。
在測試類的第一行加上下面語句,那麼在cglib中生成的class文件將會持久化到硬盤。https://www.cnblogs.com/cruze/p/3847968.html
// 該設置用於輸出cglib動態代理產生的類 System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "D:\\class"); // 該設置用於輸出jdk動態代理產生的類 System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");
反編譯結果:
// // Source code recreated from a .class file by IntelliJ IDEA // (powered by Fernflower decompiler) // package com.xiaolyuh.aop.cglib; 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 EnhancerDemo$$EnhancerByCGLIB$$da6c48f9 extends EnhancerDemo 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$test$0$Method; private static final MethodProxy CGLIB$test$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.xiaolyuh.aop.cglib.EnhancerDemo$$EnhancerByCGLIB$$da6c48f9"); 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$test$0$Method = ReflectUtils.findMethods(new String[]{"test", "()Ljava/lang/String;"}, (var1 = Class.forName("com.xiaolyuh.aop.cglib.EnhancerDemo")).getDeclaredMethods())[0]; CGLIB$test$0$Proxy = MethodProxy.create(var1, var0, "()Ljava/lang/String;", "test", "CGLIB$test$0"); } final String CGLIB$test$0() { return super.test(); } public final String test() { MethodInterceptor var10000 = this.CGLIB$CALLBACK_0; if (var10000 == null) { CGLIB$BIND_CALLBACKS(this); var10000 = this.CGLIB$CALLBACK_0; } return var10000 != null ? (String)var10000.intercept(this, CGLIB$test$0$Method, CGLIB$emptyArgs, CGLIB$test$0$Proxy) : super.test(); } final boolean CGLIB$equals$1(Object var1) { return super.equals(var1); } public final boolean equals(Object var1) { MethodInterceptor var10000 = this.CGLIB$CALLBACK_0; if (var10000 == 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; } else { return super.equals(var1); } } final String CGLIB$toString$2() { return super.toString(); } public final String toString() { MethodInterceptor var10000 = this.CGLIB$CALLBACK_0; if (var10000 == 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 (var10000 == 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 (var10000 == 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 -508378822: if (var10000.equals("clone()Ljava/lang/Object;")) { return CGLIB$clone$4$Proxy; } break; case 225925469: if (var10000.equals("test()Ljava/lang/String;")) { return CGLIB$test$0$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 EnhancerDemo$$EnhancerByCGLIB$$da6c48f9() { 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) { EnhancerDemo$$EnhancerByCGLIB$$da6c48f9 var1 = (EnhancerDemo$$EnhancerByCGLIB$$da6c48f9)var0; if (!var1.CGLIB$BOUND) { var1.CGLIB$BOUND = true; Object var10000 = CGLIB$THREAD_CALLBACKS.get(); if (var10000 == null) { var10000 = CGLIB$STATIC_CALLBACKS; if (var10000 == null) { return; } } var1.CGLIB$CALLBACK_0 = (MethodInterceptor)((Callback[])var10000)[0]; } } public Object newInstance(Callback[] var1) { CGLIB$SET_THREAD_CALLBACKS(var1); EnhancerDemo$$EnhancerByCGLIB$$da6c48f9 var10000 = new EnhancerDemo$$EnhancerByCGLIB$$da6c48f9(); CGLIB$SET_THREAD_CALLBACKS((Callback[])null); return var10000; } public Object newInstance(Callback var1) { CGLIB$SET_THREAD_CALLBACKS(new Callback[]{var1}); EnhancerDemo$$EnhancerByCGLIB$$da6c48f9 var10000 = new EnhancerDemo$$EnhancerByCGLIB$$da6c48f9(); CGLIB$SET_THREAD_CALLBACKS((Callback[])null); return var10000; } public Object newInstance(Class[] var1, Object[] var2, Callback[] var3) { CGLIB$SET_THREAD_CALLBACKS(var3); EnhancerDemo$$EnhancerByCGLIB$$da6c48f9 var10000 = new EnhancerDemo$$EnhancerByCGLIB$$da6c48f9; 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(); } }
從結果上咱們能夠看出Cglib是使用繼承的方式實現的動態代理。關鍵代碼:
public final String test() { MethodInterceptor var10000 = this.CGLIB$CALLBACK_0; if (var10000 == null) { CGLIB$BIND_CALLBACKS(this); var10000 = this.CGLIB$CALLBACK_0; } return var10000 != null ? (String)var10000.intercept(this, CGLIB$test$0$Method, CGLIB$emptyArgs, CGLIB$test$0$Proxy) : super.test(); }
從上面的代碼咱們能夠發現方法的執行會委託給MethodInterceptor的intercept方法。從而實現對方法的加強。
因爲 Cglib 是使用繼承方式,全部final類是不能使用cglib代理的,會直接拋出異常,final方法也將不會被代理,由於不能覆蓋,不會直接拋出異常
CglibAopProxy是Spring中Cglib動態代理的實現,在getProxy方法中完成了對Enhancer的建立和封裝。在getProxy方法中getCallbacks(rootClass);
方法會將攔截鏈封裝成DynamicAdvisedInterceptor對象,並放到Cglib的回調函數中。源碼以下:
@Override public Object getProxy(ClassLoader classLoader) { if (logger.isDebugEnabled()) { logger.debug("Creating CGLIB proxy: target source is " + this.advised.getTargetSource()); } try { Class<?> rootClass = this.advised.getTargetClass(); Assert.state(rootClass != null, "Target class must be available for creating a CGLIB proxy"); Class<?> proxySuperClass = rootClass; if (ClassUtils.isCglibProxyClass(rootClass)) { proxySuperClass = rootClass.getSuperclass(); Class<?>[] additionalInterfaces = rootClass.getInterfaces(); for (Class<?> additionalInterface : additionalInterfaces) { this.advised.addInterface(additionalInterface); } } // 驗證Class validateClassIfNecessary(proxySuperClass, classLoader); // 建立以及配置Enhancer Enhancer enhancer = createEnhancer(); if (classLoader != null) { enhancer.setClassLoader(classLoader); if (classLoader instanceof SmartClassLoader && ((SmartClassLoader) classLoader).isClassReloadable(proxySuperClass)) { enhancer.setUseCache(false); } } enhancer.setSuperclass(proxySuperClass); enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised)); enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE); enhancer.setStrategy(new ClassLoaderAwareUndeclaredThrowableStrategy(classLoader)); // 將攔截鏈放到回調中 Callback[] callbacks = getCallbacks(rootClass); Class<?>[] types = new Class<?>[callbacks.length]; for (int x = 0; x < types.length; x++) { types[x] = callbacks[x].getClass(); } // fixedInterceptorMap only populated at this point, after getCallbacks call above enhancer.setCallbackFilter(new ProxyCallbackFilter( this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset)); enhancer.setCallbackTypes(types); // 生成代理類並建立代理實例 return createProxyClassAndInstance(enhancer, callbacks); } ... } private Callback[] getCallbacks(Class<?> rootClass) throws Exception { // Parameters used for optimization choices... boolean exposeProxy = this.advised.isExposeProxy(); boolean isFrozen = this.advised.isFrozen(); boolean isStatic = this.advised.getTargetSource().isStatic(); // Choose an "aop" interceptor (used for AOP calls). // 將攔截鏈封裝到DynamicAdvisedInterceptor中 Callback aopInterceptor = new DynamicAdvisedInterceptor(this.advised); // Choose a "straight to target" interceptor. (used for calls that are // unadvised but can return this). May be required to expose the proxy. Callback targetInterceptor; if (exposeProxy) { targetInterceptor = isStatic ? new StaticUnadvisedExposedInterceptor(this.advised.getTargetSource().getTarget()) : new DynamicUnadvisedExposedInterceptor(this.advised.getTargetSource()); } else { targetInterceptor = isStatic ? new StaticUnadvisedInterceptor(this.advised.getTargetSource().getTarget()) : new DynamicUnadvisedInterceptor(this.advised.getTargetSource()); } // Choose a "direct to target" dispatcher (used for // unadvised calls to static targets that cannot return this). Callback targetDispatcher = isStatic ? new StaticDispatcher(this.advised.getTargetSource().getTarget()) : new SerializableNoOp(); Callback[] mainCallbacks = new Callback[] { // 將攔截鏈加入到CallBack中 aopInterceptor, // for normal advice targetInterceptor, // invoke target without considering advice, if optimized new SerializableNoOp(), // no override for methods mapped to this targetDispatcher, this.advisedDispatcher, new EqualsInterceptor(this.advised), new HashCodeInterceptor(this.advised) }; Callback[] callbacks; // If the target is a static one and the advice chain is frozen, // then we can make some optimizations by sending the AOP calls // direct to the target using the fixed chain for that method. if (isStatic && isFrozen) { Method[] methods = rootClass.getMethods(); Callback[] fixedCallbacks = new Callback[methods.length]; this.fixedInterceptorMap = new HashMap<String, Integer>(methods.length); // TODO: small memory optimization here (can skip creation for methods with no advice) for (int x = 0; x < methods.length; x++) { List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(methods[x], rootClass); fixedCallbacks[x] = new FixedChainStaticTargetInterceptor( chain, this.advised.getTargetSource().getTarget(), this.advised.getTargetClass()); this.fixedInterceptorMap.put(methods[x].toString(), x); } // Now copy both the callbacks from mainCallbacks // and fixedCallbacks into the callbacks array. callbacks = new Callback[mainCallbacks.length + fixedCallbacks.length]; System.arraycopy(mainCallbacks, 0, callbacks, 0, mainCallbacks.length); System.arraycopy(fixedCallbacks, 0, callbacks, mainCallbacks.length, fixedCallbacks.length); this.fixedInterceptorOffset = mainCallbacks.length; } else { callbacks = mainCallbacks; } return callbacks; }
java動態代理是利用反射機制生成一個實現代理接口的匿名類,在調用具體方法前調用InvokeHandler來處理。而cglib動態代理是利用asm開源包,對代理對象類的class文件加載進來,經過修改其字節碼生成子類來處理。
結論:從 jdk6 到 jdk七、jdk8 ,動態代理的性能獲得了顯著的提高,尤爲是JDK7和JDK8性能表現都比cglib好,而 cglib 的表現並未跟上,甚至可能會略微降低。因此建議儘可能使用 JDK 的動態代理。
https://github.com/wyh-spring-ecosystem-student/spring-boot-student/tree/releases
spring-boot-student-spring 工程