天天看點

Spring AOP原理1 生成代理對象2 JDK動态代理與invoke方法驅動AOP增強3 CGLIB與intercept方法驅動AOP增強4 SpringAOP過程總結

Spring利用動态代理技術實作了AOP增強功能。這個動态代理是通過Java的動态代理或CGLIB技術實作。具體根據代理對象實作的是類或者接口來決定。

Spring AOP的過程跟我們平時使用動态代理的過程是很相似的,隻不過它幫助我們自動組裝了增強方法與代理對象,這樣我們就可以更加靈活,因為我們可以選擇增強觸發的時機,而且更加關注我們要做的事情。從原理以及源代碼的角度,整個過程還是分為兩個階段,

第一個階段是生成代理對象,這個過程根據代理對象是否實作了接口來選擇使用不同的工廠生成代理對象。

第二個階段是invoke階段,也就是方法調用階段。所有的切入點判斷、advice增強都是在這個階段完成的。個人了解隻有這樣才能算是動态代理吧。

Spring AOP原理1 生成代理對象2 JDK動态代理與invoke方法驅動AOP增強3 CGLIB與intercept方法驅動AOP增強4 SpringAOP過程總結

1 生成代理對象

1.1 getObject

先來回憶一下我們是如何在程式中拿到代理對象的

InstanceInterface bean=(InstanceInterface) applicationContext.getBean("beanFactory");
           

我們是通過ProxyFactoryBean這個工廠bean得到的代理對象。根據工廠Bean的特點,它一定實作了FactoryBean接口,也就一定包含有getObject方法,沒錯,這就是獲得代理對象的入口。這個方法實作的也很簡單:

public Object getObject() throws BeansException {
		//初始化advisor方法鍊
		initializeAdvisorChain();
		if (isSingleton()) {
			//傳回單例執行個體
			return getSingletonInstance();
		}
		else {
			if (this.targetName == null) {
				logger.warn("Using non-singleton proxies with singleton targets is often undesirable. " +
						"Enable prototype proxies by setting the 'targetName' property.");
			}
			//傳回prototype執行個體
			return newPrototypeInstance();
		}
	}
           

1.2 getSingletonInstance

這個方法調用了AopProxy的工廠方法來得到代理對象

private synchronized Object getSingletonInstance() {
		if (this.singletonInstance == null) {
			//獲得目标對象
			this.targetSource = freshTargetSource();
			if (this.autodetectInterfaces && getProxiedInterfaces().length == 0 && !isProxyTargetClass()) {
				// Rely on AOP infrastructure to tell us what interfaces to proxy.
				Class<?> targetClass = getTargetClass();
				if (targetClass == null) {
					throw new FactoryBeanNotInitializedException("Cannot determine target class for proxy");
				}
				setInterfaces(ClassUtils.getAllInterfacesForClass(targetClass, this.proxyClassLoader));
			}
			// Initialize the shared singleton instance.
			super.setFrozen(this.freezeProxy);
			//調用工程方法得到代理對象 
			this.singletonInstance = getProxy(createAopProxy());
		}
		return this.singletonInstance;
	}
           

1.3構造代理工廠

@Override
	public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
		if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
			Class<?> targetClass = config.getTargetClass();
			if (targetClass == null) {
				throw new AopConfigException("TargetSource cannot determine target class: " +
						"Either an interface or a target is required for proxy creation.");
			}
			if (targetClass.isInterface()) {
				//如果目标對象實作了接口  則構造一個JDK動态代理工程
				return new JdkDynamicAopProxy(config);
			}
			//否則構造一個CGLIB動态代理工廠
			return new ObjenesisCglibAopProxy(config);
		}
		else {
			return new JdkDynamicAopProxy(config);
		}
	}
           

1.4 得到代理對象

這裡由于構造了兩個工廠,是以其生成代理對象的方式也有所不同

1.4.1 JDK生成代理對象

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);
		//非常熟悉的JDK生成代理對象的方式
		return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
	}
           

1.4.2  CGLIB生成代理對象

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.
			validateClassIfNecessary(proxySuperClass, classLoader);

			// 配置CGLIB 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 UndeclaredThrowableStrategy(UndeclaredThrowableException.class));

			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);

			// Generate the proxy class and create a proxy instance.
			return createProxyClassAndInstance(enhancer, callbacks);
		}
		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);
		}
	}
           

1.5 小結

到此為止,spring就通過了proxyFactoryBean為我們生成了代理對象,目前這個代理對象還沒有進行任何增強方法的織入,隻是将Advisor對象注入到了這個對象裡面。下面我們來看看spring是如何實作AOP的。

2 JDK動态代理與invoke方法驅動AOP增強

我們知道在使用動态代理的時候,我們盡管看上去是調用的目标對象接口或實作類的方法,實際上執行的确是代理對象的invoke方法。在Spring AOP中自然也不例外,那麼這個invoke方法是定義在哪裡呢?我們以JDK生成動态代理的方式來解釋這一過程。

2.1 invoke方法

這個invoke方法實際上定義在JdkDynamicAopProxy類中,他實作了我們熟悉的InvocationHandler接口。這個方法是整個AOP過程的提綱,整個過程的幾個核心步驟都在此處進行了調用。特别需要注意的是,對于equals和hashcode方法,spring是不會對他們進行增強處理的。

@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  hashcode方法不做AOP增強,直接執行方法
			if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
				// The target does not implement the equals(Object) method itself.
				return equals(args[0]);
			}
			if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
				// The target does not implement the hashCode() method itself.
				return hashCode();
			}
			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.
			// 獲得AOP攔截方法鍊 在這裡面完成了pointcut與advice的比對 它确定了這個方法都需要有哪些增強處理
			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()) {
				
				// 如果方法鍊為空,那麼不執行任何增強處理,直接調用方法
				retVal = AopUtils.invokeJoinpointUsingReflection(target, method, args);
			}
			else {
				// 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);
			}
		}
	}
           

2.2 擷取比對的advice方法

這個方法是在獲得advice方法鍊,實際上利用AdvisorChainFactory工廠得到這些對象。

這裡設定了緩存,也就是說隻有第一次調用這個方法時,才會有這個擷取比對的advice對象的。需要了解的是,advice被定義在advisor裡面,而整個方法鍊可能有多少advisor,也就是說可能有多個methodbefore afterrunning之類的方法圍繞在實際方法周圍,這些方法在這裡進行比對,然後放到一個list中。

public List<Object> getInterceptorsAndDynamicInterceptionAdvice(Method method, Class<?> targetClass) {
		//緩存對象
		MethodCacheKey cacheKey = new MethodCacheKey(method);
		List<Object> cached = this.methodCache.get(cacheKey);
		if (cached == null) {
			//通過工廠得到比對的advice對象
			cached = this.advisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice(
					this, method, targetClass);
			this.methodCache.put(cacheKey, cached);
		}
		return cached;
	}
           

2.2.1 裝配攔截器

這個方法定義在DefaultAdvisorChainFactory類中,在這裡完成了pointcut與advice的比對。其中兩個重要的語句分别在20行和24行。他們分别完成了advice的封裝以及pointcut與method的比對兩個工作。

public List<Object> getInterceptorsAndDynamicInterceptionAdvice(
			Advised config, Method method, Class<?> targetClass) {

		// This is somewhat tricky... We have to process introductions first,
		// but we need to preserve order in the ultimate list.
		List<Object> interceptorList = new ArrayList<Object>(config.getAdvisors().length);
		Class<?> actualClass = (targetClass != null ? targetClass : method.getDeclaringClass());
		boolean hasIntroductions = hasMatchingIntroductions(config, actualClass);
		AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();
		//便利所有的advisor 
		for (Advisor advisor : config.getAdvisors()) {
			if (advisor instanceof PointcutAdvisor) {
				// Add it conditionally.
				
				// 獲得方法切入點
				PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor;
				if (config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(actualClass)) {
					
					//獲得advisor中定義的advice對象,也就是methodBeforeAdvice  afterRunningAdvice 和ThrowsAdvice  
					MethodInterceptor[] interceptors = registry.getInterceptors(advisor);
					//得到一個方法比對器
					MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher();
					//進行方法比對,如果這個方法符合pointcut中的定義,就把advice對象攔截器加入到結果集中
					if (MethodMatchers.matches(mm, method, actualClass, hasIntroductions)) {
						if (mm.isRuntime()) {
							// Creating a new object instance in the getInterceptors() method
							// isn't a problem as we normally cache created chains.
							for (MethodInterceptor interceptor : interceptors) {
								interceptorList.add(new InterceptorAndDynamicMethodMatcher(interceptor, mm));
							}
						}
						else {
							interceptorList.addAll(Arrays.asList(interceptors));
						}
					}
				}
			}
			else if (advisor instanceof IntroductionAdvisor) {
				IntroductionAdvisor ia = (IntroductionAdvisor) advisor;
				if (config.isPreFiltered() || ia.getClassFilter().matches(actualClass)) {
					Interceptor[] interceptors = registry.getInterceptors(advisor);
					interceptorList.addAll(Arrays.asList(interceptors));
				}
			}
			else {
				Interceptor[] interceptors = registry.getInterceptors(advisor);
				interceptorList.addAll(Arrays.asList(interceptors));
			}
		}

		return interceptorList;
	}
           

2.2.2 封裝advice

先來回想一下我們是如何定義advice的。我們可以分别實作MethodBeforeAdvice AfterReturningAdvice 和ThrowsAdvice這三個接口來定義三個增強的動作,然後在spring配置檔案中配置了他們與pointcut的關系,成為一個advisor。在spring進行AOP增強的時候,需要把這三種advice進行一次包裝,也就是在把他們其中定義的增強方法與實際方法聯系起來,構造一個方法“鍊”,這個就是封裝advice的過程。

整個過程的入口為2.2.1中的20行getInterceptors方法。顧名思義,它就是獲得所有攔截器的一個方法。進入到這個方法,發現突然出現了一個陌生的東西,AdvisorAdapter,還有一個this. adapters。他們其實是MethodBeforeAdviceAfterReturningAdvice和ThrowsAdvice的裝配器。在這裡的作用就是為了确定我們定義的advice到底是哪種或者哪幾種類型的advice。

public MethodInterceptor[] getInterceptors(Advisor advisor) throws UnknownAdviceTypeException {
		// 這個list是固定大小的  因為一個advice中 最多有三種類型的攔截器,也就是同時實作了三種類型的接口
		List<MethodInterceptor> interceptors = new ArrayList<MethodInterceptor>(3);
		Advice advice = advisor.getAdvice();
		//如果這個advice實作了MethodInterceptor接口 就把它直接加入進去
		if (advice instanceof MethodInterceptor) {
			interceptors.add((MethodInterceptor) advice);
		}
		//判斷advice屬于三個類型的中那幾種類型 
		for (AdvisorAdapter adapter : this.adapters) {
			if (adapter.supportsAdvice(advice)) {
				//對這個方法進行包裝
				interceptors.add(adapter.getInterceptor(advisor));
			}
		}
		if (interceptors.isEmpty()) {
			throw new UnknownAdviceTypeException(advisor.getAdvice());
		}
		return interceptors.toArray(new MethodInterceptor[interceptors.size()]);
	}
           

Spring中為三種advice均定義了對應類型的裝配器adapter,他們的實作方法幾乎是一樣的,我們來看其中一個就能了解上面的代碼了。

class AfterReturningAdviceAdapter implements AdvisorAdapter, Serializable {

	@Override
	//判斷這個advice是否屬于目前類型的advice
	public boolean supportsAdvice(Advice advice) {
		
		return (advice instanceof AfterReturningAdvice);
	}

	@Override
	//對這個adivce進行包裝
	public MethodInterceptor getInterceptor(Advisor advisor) {
		AfterReturningAdvice advice = (AfterReturningAdvice) advisor.getAdvice();
		return new AfterReturningAdviceInterceptor(advice);
	}

}
           

2.2.3 三種類型的interceptor

經過了上面一步,我們定義的advice已經被封裝了對應了Interceptor,在這三種類型的Interceptor中,進行了編織工作,也就是把我們定義的增強方法與實際方法進行了組合,下面我們分别看看他們是如何實作的。

(1) AfterReturningAdviceInterceptor

這裡有一個invoke方法,可以看到實際方法在增強方法之前得到調用,也就起到了後處理的作用。這裡的proceed暫且認為是方法調用,在後面會看到它是如何實作的。

@Override
	public Object invoke(MethodInvocation mi) throws Throwable {
//調用實際方法
		Object retVal = mi.proceed();
		//調用自定義的增強方法
		this.advice.afterReturning(retVal, mi.getMethod(), mi.getArguments(), mi.getThis());
		return retVal;
	}
           

(2) MethodBeforeAdviceInterceptor

這裡有一個invoke方法,可以看到實際方法在增強方法之後得到調用,起到了前置增強的作用。

@Override
	public Object invoke(MethodInvocation mi) throws Throwable {
		// 調用自定義增強方法
		this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis() );
		//調用實際方法
		return mi.proceed();
	}
           

(3)  ThrowsAdviceInterceptor

這裡面的代碼就沒有上面的那麼簡單了,但是邏輯還是比較清晰的。在invoke中定義了一個trycatch,把實際方法放入到try語句塊中,一旦抛出異常,就會被捕獲,然後去尋找我們是否定義了對應的異常處理方法,調用我們定義的處理方法進行處理。這實際上也就是一個更進階一點的try catch語句塊而已。

/**
	 * Determine the exception handle method. Can return null if not found.
	 * @param exception the exception thrown
	 * @return a handler for the given exception type
	 */
	private Method getExceptionHandler(Throwable exception) {
		Class<?> exceptionClass = exception.getClass();
		if (logger.isTraceEnabled()) {
			logger.trace("Trying to find handler for exception of type [" + exceptionClass.getName() + "]");
		}
		Method handler = this.exceptionHandlerMap.get(exceptionClass);
		while (handler == null && !exceptionClass.equals(Throwable.class)) {
			exceptionClass = exceptionClass.getSuperclass();
			handler = this.exceptionHandlerMap.get(exceptionClass);
		}
		if (handler != null && logger.isDebugEnabled()) {
			logger.debug("Found handler for exception of type [" + exceptionClass.getName() + "]: " + handler);
		}
		return handler;
	}

	@Override
	public Object invoke(MethodInvocation mi) throws Throwable {
		try {
			return mi.proceed();
		}
		catch (Throwable ex) {
			Method handlerMethod = getExceptionHandler(ex);
			if (handlerMethod != null) {
				invokeHandlerMethod(mi, ex, handlerMethod);
			}
			throw ex;
		}
	}

	private void invokeHandlerMethod(MethodInvocation mi, Throwable ex, Method method) throws Throwable {
		Object[] handlerArgs;
		if (method.getParameterTypes().length == 1) {
			handlerArgs = new Object[] { ex };
		}
		else {
			handlerArgs = new Object[] {mi.getMethod(), mi.getArguments(), mi.getThis(), ex};
		}
		try {
			method.invoke(this.throwsAdvice, handlerArgs);
		}
		catch (InvocationTargetException targetEx) {
			throw targetEx.getTargetException();
		}
	}

           

2.3   proceed方法鍊調用

前面有一個地方提到了一個proceed方法,我們再回到2.1invoke方法中,整個2.2過程講的就是45行代碼獲得方法鍊的過程。經過了這個過程,我們已經得到了定義AOP需要的方法鍊,下面就應該進行方法調用了。這裡面涉及兩個關鍵方法,proceed和invokeJoinpointUsingReflection,他們分别是在還有方法鍊和方法鍊已經為空的時候調用的。

2.3.1    invokeJoinpointUsingReflection

它是定義在AopUtils工具類中的一個靜态方法,實作的很簡單,就是用反射去調用目标方法。

public static Object invokeJoinpointUsingReflection(Object target, Method method, Object[] args)
			throws Throwable {

		// Use reflection to invoke the method.
		try {
			ReflectionUtils.makeAccessible(method);
			//調用實際方法
			return method.invoke(target, args);
		}
		catch (InvocationTargetException ex) {
			// Invoked method threw a checked exception.
			// We must rethrow it. The client won't see the interceptor.
			throw ex.getTargetException();
		}
		catch (IllegalArgumentException ex) {
			throw new AopInvocationException("AOP configuration seems to be invalid: tried calling method [" +
					method + "] on target [" + target + "]", ex);
		}
		catch (IllegalAccessException ex) {
			throw new AopInvocationException("Could not access method [" + method + "]", ex);
		}
	}
           

2.3.2  proceed

這個方法驅動整個方法鍊的方法,它實際上是一個遞歸的過程。它從方法鍊list中依次獲得對應的interceptor,并調用的他們invoke方法,再回想2.2.3中提到的proceed,調用invoke以後會遞歸地再次調用proceed方法,這樣就驅動了整個方法鍊的調用,也就完成了AOP的過程。

public Object proceed() throws Throwable {
	
		//	如果方法鍊已經到了最後一個方法,那就是目标方法,直接調用該方法,使用的是2.3.1中的反射
		if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
			return invokeJoinpoint();
		}
		//依次從方法鍊list中獲得相對應的 interceptor
		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 {
			//調用對應interceptor中的invoke方法
			return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
		}
	}
           

3 CGLIB與intercept方法驅動AOP增強

在前面介紹了通過JDK動态代理的方式實作了AOP增強,它的核心是invoke觸發了方法鍊的調動。CGLIB的整個過程是十分類似的,關鍵的方法也都是一樣的,隻不過在使用GCLIB生成代理對象的時候,advisor被設定在CALLBACK裡,其關鍵語句在CglibAopProxy類(本例源自Spring4.1.5版本,在3.2版本中,這個類名為Cglib2AopProxy)中的getCallBacks方法中。

Callback aopInterceptor = new DynamicAdvisedInterceptor(this.advised);
           

所有的advice對象被封裝在了DynamicAdvisedInterceptor這個内部類對象中,而正是這個類裡面定義的intercept方法驅動了AOP過程。

看這個方法的源代碼,幾乎是跟invoke方法一樣的,而且連注釋都是一緻的。隻有一個地方是不同的,對于proceed的調用,cglib使用的是CglibMethodInvocation的方法,而jdk使用的是ReflectiveMethodInvocation,而他們的關系是繼承關系,也就是說CGLIB在進入到AOP增強的實作部分與JDK動态代理的部分沒有差別。

@Override
		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 {
					// 遞歸調用方法鍊
					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);
				}
			}
		}
           

4 SpringAOP過程總結

經過了上面的分析,發現AOP的過程并不複雜。就如開篇所說,它分為兩個部分

第一是得到代理對象,這裡根據目标對象的不同,可以使用JDK動态代理或者CGLIB來生成代理對象,對于Advisor,僅是将他們設定到對應的對象中,并沒有進行任何其他的處理

第二個過程是AOP方法驅動的過程,對于目标方法的調用,他們或是驅動了invoke方法,或是調用了intercept方法,這樣就進入到AOP增強的過程。在這個過程中,完成了獲得advice方法,封裝advice方法到對應的interceptor,組裝advice方法鍊,遞歸調用proceed方法這一系列的過程,這樣就完成了AOP增強的功能。

Spring AOP原理1 生成代理對象2 JDK動态代理與invoke方法驅動AOP增強3 CGLIB與intercept方法驅動AOP增強4 SpringAOP過程總結

繼續閱讀