咱們知道spring org\springframework\aop\framework\DefaultAopProxyFactory.java#createAopProxy的方法返回的JdkDynamicAopProxy 或 CglibProxyFactory 實現了建立代理類的邏輯,分別支持jdk和cglib兩種代理方式。java
jdk 代理方式僅支持對一個接口建立代理對象,也就是被代理的對象必須實現某個接口。spring
cglib 代理主要是針對類實現代理,基本實現思路是動態生成被代理類的子類,從而能夠代理父類的全部方法。app
在瞭解spring aop實現邏輯以前咱們先回顧一下這兩種代理方式。框架
package framework.aop; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; /** * 這是 spring JdkDynamicAopProxy 的精簡版實現, * 其實原理很簡單,spring也是用Proxy和 InvocationHandler 這兩個類建立代理對象。 * * 在整個過程當中,InvocationHandler 的 invoke 方法最重要,全部的代理邏輯所有在這裏實現。 */ public class JdkProxyDemo { public static void main(String[] args) { FooInterface foo = new FooImpl(); FooHandler fooHandler = new FooHandler(foo); foo = (FooInterface)fooHandler.getProxy(); foo.hello(); } } interface FooInterface{ void hello(); } class FooImpl implements FooInterface{ @Override public void hello() { System.out.println("hello."); } } class FooHandler implements InvocationHandler{ Object target; public FooHandler(Object obj){ this.target = obj; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("before..."); Object result = method.invoke(target,args); System.out.println("after..."); return result; } public Object getProxy(){ return Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(), target.getClass().getInterfaces(),this); } }
運行結果以下:ide
before... hello. after...
JdkDynamicAopProxy的getProxy方法返回代理方法工具
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); findDefinedEqualsAndHashCodeMethods(proxiedInterfaces); return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this); }
咱們知道 jdk 代理的關鍵邏輯是在invoke中,下面是sping 的實現性能
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]); } // hascode 方法的處理 if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) { // The target does not implement the hashCode() method itself. return hashCode(); } /* class 類的isAssignableFrom(Class cls)方法: 若是調用這個方法的是class或接口與參數cls表示的類或接口相同, 或者是參數cls表示的類或接口的弗雷,則返回true. 形象地:自身類.class.isAssignableFrom(自身類或四類.class) 返回true eg. System.out.println(ArrayList.class.isAssignableFrom(Object.class) == false); System.out.println(Object.class.isAssignableFrom(ArrayList.class) == true); */ 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(); } // Get the interception chain for this method. // 獲取當前方法的攔截器 List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass); // Check whether we have any advice. If we don't, we can fallback on direct // reflective invocation of the target, and avoid creating a MethodInvocation. if (chain.isEmpty()) { // We can skip creating a MethodInvocation: just invoke the target directly // Note that the final invoker must be an InvokerInterceptor so we know it does // nothing but a reflective operation on the target, and no hot swapping or fancy proxying. retVal = AopUtils.invokeJoinpointUsingReflection(target, method, args); } else { // importance We need to create a method invocation... invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain); // Proceed to the joinpoint through the interceptor chain. retVal = invocation.proceed(); } // Massage return value if necessary. Class<?> returnType = method.getReturnType(); if (retVal != null && retVal == target && 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); } } }
上面最重主要的工做就是建立一個 ReflectiveMethodInvocation 封裝了鏈接器鏈。測試
ReflectiveMethodInvocation#proceedui
public Object proceed() throws Throwable { // We start with an index of -1 and increment early. if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) { return invokeJoinpoint(); } // 獲取下一個要執行的攔截器 Object interceptorOrInterceptionAdvice = this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex); if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) { // Evaluate dynamic method matcher here: static part will already have // been evaluated and found to match. InterceptorAndDynamicMethodMatcher dm = (InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice; if (dm.methodMatcher.matches(this.method, this.targetClass, this.arguments)) { return dm.interceptor.invoke(this); } else { // Dynamic matching failed. // Skip this interceptor and invoke the next in the chain. return proceed(); } } else { // 普通攔截器,直接調用攔截器,如: // ExposeInvocationInterceptor // DelegatePertargetObjectInteroductionInterceptor // MethodBeforeAdviceInterceptor // AspectJAroundAdvice // AspectJAfterAdvice // 將 this做爲參數傳遞一保證當前實例中調用連的執行 // It's an interceptor, so we just invoke it: The pointcut will have // been evaluated statically before this object was constructed. return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this); } }
這個方法的邏輯並不負責,主要負責責任鏈的調用,記錄當前責任鏈調用位置,以便有序的進行調用。this
CGLIB是一個強大的高性能的代碼生成包。它普遍的被許多AOP的框架使用,例如Spring AOP和dynaop,爲他們提供方法的interception(攔截)。最流行的OR Mapping工具hibernate也使用CGLIB來代理單端single-ended(多對一和一對一)關聯(對集合的延遲抓取,是採用其餘機制實 現的)。EasyMock和jMock是經過使用模仿(moke)對象來測試java代碼的包。它們都經過使用CGLIB來爲那些沒有接口的類建立模仿 (moke)對象。
CGLIB包的底層是經過使用一個小而快的字節碼處理框架ASM,來轉換字節碼並生成新的類。除了CGLIB包,腳本語言例如 Groovy和BeanShell,也是使用ASM來生成java的字節碼。當不鼓勵直接使用ASM,由於它要求你必須對JVM內部結構包括class文 件的格式和指令集都很熟悉。
public class CglibEnhancerDemo { public static void main(String[] args) { Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(CglibEnhancerDemo.class); enhancer.setCallback(new MethodInterceptorImpl()); CglibEnhancerDemo demo = (CglibEnhancerDemo)enhancer.create(); demo.test(); System.out.println(demo); } public void test() { System.out.println("test..."); } private static class MethodInterceptorImpl implements MethodInterceptor{ public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable { System.out.println("before invoke" + method); Object result = methodProxy.invokeSuper(o,objects); System.out.println("after invoke"+method); return result; } } }
cglib 是經過吧MethodInterceptor加到 callBack中,對於方法的連接是經過鏈接器中的intercept方法來實現的。在吧MethodInterceptor加入到callback中後,在調用代理是會直接調用intercept方法,實現代理邏輯。
運行結果以下
before invoke public void bean.aop.CglibEnhancerDemo.test() test... after invoke public void bean.aop.CglibEnhancerDemo.test() before invoke public java.lang.String java.lang.Object.toString() before invoke public native int java.lang.Object.hashCode() after invoke public native int java.lang.Object.hashCode() after invoke public java.lang.String java.lang.Object.toString() bean.aop.CglibEnhancerDemo$$EnhancerByCGLIB$$efbf68ac@a8ceb6
咱們看到System.out.println(demo)這行代碼運行時,會調用對象的toString,hasCode,最後打印的是bean.aop.CglibEnhancerDemo$$EnhancerByCGLIB$$efbf68ac@a8ceb6,是由cglib運行時產生的代理對象。
spring 委託CglibAopProxy建立 cglib 代理,看過了 jdk代理的初始化方式,咱們知道 getProxy 方法確定實現了 Enhancer 的建立和接口的封裝。
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); } } // Validate the class, writing log messages as necessary. // 驗證class validateClassIfNecessary(proxySuperClass); // Configure CGLIB Enhancer... // 建立和配置 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 MemorySafeUndeclaredThrowableStrategy(UndeclaredThrowableException.class)); enhancer.setInterceptDuringConstruction(false); //importance 設置攔截器 Callback[] callbacks = getCallbacks(rootClass); Class<?>[] types = new Class<?>[callbacks.length]; for (int x = 0; x < types.length; x++) { types[x] = callbacks[x].getClass(); } enhancer.setCallbackFilter(new ProxyCallbackFilter( this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset)); enhancer.setCallbackTypes(types); enhancer.setCallbacks(callbacks); // Generate the proxy class and create a proxy instance. // 生成代理類,建立對象 Object proxy; if (this.constructorArgs != null) { proxy = enhancer.create(this.constructorArgTypes, this.constructorArgs); } else { proxy = enhancer.create(); } return proxy; } catch (CodeGenerationException ex) { throw new AopConfigException("Could not generate CGLIB subclass of class [" + this.advised.getTargetClass() + "]: " + "Common causes of this problem include using a final class or a non-visible class", ex); } catch (IllegalArgumentException ex) { throw new AopConfigException("Could not generate CGLIB subclass of class [" + this.advised.getTargetClass() + "]: " + "Common causes of this problem include using a final class or a non-visible class", ex); } catch (Exception ex) { // TargetSource.getTarget() failed throw new AopConfigException("Unexpected AOP exception", ex); } }
這裏最重要的而是經過 getCallbacks 方法設置鏈接器鏈。
private Callback[] getCallbacks(Class<?> rootClass) throws Exception { // Parameters used for optimisation 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 optimisations 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 optimisation 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; }
spring在這個方法裏考慮了不少狀況,如exposeProxy暴露代理對象等,咱們只解釋DynamicAdvisedInterceptor。DynamicAdvisedInterceptor加入callBack實現代理邏輯,核心邏輯必定在intercept方法中。
private static class DynamicAdvisedInterceptor implements MethodInterceptor, Serializable { private final AdvisedSupport advised; public DynamicAdvisedInterceptor(AdvisedSupport advised) { this.advised = advised; } public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable { Object oldProxy = null; boolean setProxyContext = false; Class<?> targetClass = null; Object target = null; try { 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 = getTarget(); if (target != null) { targetClass = target.getClass(); } // 獲取攔截器鏈 List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass); Object retVal; // Check whether we only have one InvokerInterceptor: that is, // no real advice, but just reflective invocation of the target. if (chain.isEmpty() && Modifier.isPublic(method.getModifiers())) { // We can skip creating a MethodInvocation: just invoke the target directly. // Note that the final invoker must be an InvokerInterceptor, so we know // it does nothing but a reflective operation on the target, and no hot // swapping or fancy proxying. // 若是攔截器爲空,直接調用原方法 retVal = methodProxy.invoke(target, args); } else { // We need to create a method invocation... // 調用攔截器鏈 retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed(); } retVal = processReturnType(proxy, target, method, retVal); return retVal; } finally { if (target != null) { releaseTarget(target); } if (setProxyContext) { // Restore old proxy. AopContext.setCurrentProxy(oldProxy); } } }
無論是jdk代理仍是cglib代理,都是首先構造責任鏈,而後封裝此鏈記性串聯調用,稍微有些區別就是jdk中直接構造ReflectiveMethodInvocation,而cglib中使用CglibMethodInvocation。