1. 程式人生 > >spring原始碼閱讀(2)-aop之原始碼解析篇

spring原始碼閱讀(2)-aop之原始碼解析篇

經過一個aop術語介紹和動態代理的深入講解,我們終於可以來看aop的原始碼了,下面跟著博主一點點剖析spring aop原始碼的實現吧

我們知道spring使用中我們只要做好相關的配置,spring自動幫我們做好了代理的相關工作。

我們從三個方面入手吧

1、配置

2、建立代理

3、獲取代理類

配置

我們從AopNamespaceHandler入手,這個是自定義配置的實現類

public void init() {
        this.registerBeanDefinitionParser("config", new ConfigBeanDefinitionParser());
        this.registerBeanDefinitionParser("aspectj-autoproxy", new AspectJAutoProxyBeanDefinitionParser());
    }

對aop的aspectj的配置很熟悉了吧

我們來看看AspectJAutoProxyBeanDefinitionParser的parse方法吧,這個是ioc載入自定義配置呼叫的方法

public BeanDefinition parse(Element element, ParserContext parserContext) {
		AopNamespaceUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(parserContext, element);
	}

public static void registerAspectJAnnotationAutoProxyCreatorIfNecessary(
			ParserContext parserContext, Element sourceElement) {
        //註冊AspectJAnnotationAutoProxyCreator
		BeanDefinition beanDefinition = AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(
				parserContext.getRegistry(), parserContext.extractSource(sourceElement));
        //處理proxy-target-class和expose-proxy

		useClassProxyingIfNecessary(parserContext.getRegistry(), sourceElement);
    //註冊元件
		registerComponentIfNecessary(beanDefinition, parserContext);
	}


        //註冊的是AnnotationAwareAspectJAutoProxyCreator
public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry, Object source) {
		return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);
	}

這裡我們注意,springaop自動幫我們註冊了AnnotationAwareAspectJAutoProxyCreator

另外target-proxy-class:spring提供了兩種代理的,jdk和cglib(建議使用jdk),這個屬性就是配置使用哪個代理模式的true-cglib,false-jdk

expose-proxy:解決那日不自我呼叫無法增強

建立代理

我們看看AnnotationAwareAspectJAutoProxyCreator的UML類關係圖

可以看出AbstractAutoProxyCreator實現了BeanPostProcessor方法,看到這個我想我們應該知道去關注什麼方法吧,對postProcessAfterInitialization是建立bean的時候會執行的方法

public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
		if (bean != null) {
			Object cacheKey = getCacheKey(bean.getClass(), beanName);
			if (!this.earlyProxyReferences.containsKey(cacheKey)) {
				return wrapIfNecessary(bean, beanName, cacheKey);
			}
		}
		return bean;
	}

什麼快取之類的我們先不看了,因為這個時候還沒有

if (beanName != null && this.targetSourcedBeans.containsKey(beanName)) {
			return bean;
		}
		

		// 獲取bean的切面
		Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
		if (specificInterceptors != DO_NOT_PROXY) {
            //建立代理物件
			Object proxy = createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
		}

		return bean;
}

我們先來看看增強的獲取:

1、
protected Object[] getAdvicesAndAdvisorsForBean(Class beanClass, String beanName, TargetSource targetSource) {
		List advisors = findEligibleAdvisors(beanClass, beanName);
		if (advisors.isEmpty()) {
			return DO_NOT_PROXY;
		}
		return advisors.toArray();
	}

2、
protected List<Advisor> findEligibleAdvisors(Class beanClass, String beanName) {
           //尋找所有的增強
		List<Advisor> candidateAdvisors = findCandidateAdvisors();
        //匹配適應的增強,無法找到返回null
		List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
		extendAdvisors(eligibleAdvisors);
		if (!eligibleAdvisors.isEmpty()) {
            //排序增強
			eligibleAdvisors = sortAdvisors(eligibleAdvisors);
		}
		return eligibleAdvisors;
	}

在過來看看代理的建立

protected Object createProxy(
			Class<?> beanClass, String beanName, Object[] specificInterceptors, TargetSource targetSource) {

		ProxyFactory proxyFactory = new ProxyFactory();
		
        //新增代理介面
		if (!shouldProxyTargetClass(beanClass, beanName)) {
			// Must allow for introductions; can't just set interfaces to
			// the target's interfaces only.
			Class<?>[] targetInterfaces = ClassUtils.getAllInterfacesForClass(beanClass, this.proxyClassLoader);
			for (Class<?> targetInterface : targetInterfaces) {
				proxyFactory.addInterface(targetInterface);
			}
		}
        //新增增強
		Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
		for (Advisor advisor : advisors) {
			proxyFactory.addAdvisor(advisor);
		}

		proxyFactory.setTargetSource(targetSource);

		return proxyFactory.getProxy(this.proxyClassLoader);
	}

直接看getProxy()

public Object getProxy(ClassLoader classLoader) {
		return createAopProxy().getProxy(classLoader);
	}

我先看看createAopFactory建立了什麼代理類

protected final synchronized AopProxy createAopProxy() {
		if (!this.active) {
			activate();
		}
		return getAopProxyFactory().createAopProxy(this);
	}

public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
        //判斷配置,optimize配置為true或者proxy-target-class=true
        //且目標類是一個介面使用jdk
        //或者使用cglib
		if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
			Class targetClass = config.getTargetClass();
			
			if (targetClass.isInterface()) {
				return new JdkDynamicAopProxy(config);
			}
			return CglibProxyFactory.createCglibProxy(config);
		}
        //optimize配置為false並且proxy-target-class=false直接使用jdk代理
		else {
			return new JdkDynamicAopProxy(config);
		}
	}

看到了吧,這裡就決定了代理的建立方式,optimize為false且proxy-target-class=false,且不存在使用代理介面直接使用jdk,否則再判斷如果目標類是一個介面,則使用jdk,否則使用cglib。

先剖析Jdk的getProxy

我們來看下JdkDynamicAopProxy的類關係圖

從上圖可知,JdkDynamicAopProxy實現了InvocationHandler,也就是代理的邏輯操作在這裡面實現

再看看getProxy這個函式

public Object getProxy(ClassLoader classLoader) {
		
		Class[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised);
		findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
		return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
	}

這裡的return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);就是建立代理類了

我們看看jdk的關鍵InvocationHandler的實現吧

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
			
			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);

			// 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 {
				// 封裝攔截鏈
				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.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;
		}
		
	}

這裡比較重要的就是攔截鏈了,我們接下來剖析一下攔截鏈的執行

public Object proceed() throws Throwable {
		//	執行完所有攔截器鏈後,執行切點方法
		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 {
				//匹配失敗,不執行啥
				return proceed();
			}
		}
		else {
			//普通攔截器直接呼叫攔截器,處理引介增強
			return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
		}
	}

這裡就是通過一個索引遍歷列表的,注意一下這個InterceptorAndDynamicMethodMatcher類

class InterceptorAndDynamicMethodMatcher {

	final MethodInterceptor interceptor;

	final MethodMatcher methodMatcher;

	public InterceptorAndDynamicMethodMatcher(MethodInterceptor interceptor, MethodMatcher methodMatcher) {
		this.interceptor = interceptor;
		this.methodMatcher = methodMatcher;
	}

}

其實就是一個方法匹配攔截器,這裡我們在回到上面的建立攔截器鏈的方法,看看怎麼建立攔截器的

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

		
		List<Object> interceptorList = new ArrayList<Object>(config.getAdvisors().length);

        //獲取所有的增強器
		for (Advisor advisor : config.getAdvisors()) {
            //判斷增強是否有切點
			if (advisor instanceof PointcutAdvisor) {
				
				PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor;
				if (config.isPreFiltered() || 
                //類過濾器匹配
pointcutAdvisor.getPointcut().getClassFilter().matches(targetClass)) {
					MethodInterceptor[] interceptors = registry.getInterceptors(advisor);
					MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher();
                    //方法匹配器匹配
					if (MethodMatchers.matches(mm, method, targetClass, 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(targetClass)) {
					Interceptor[] interceptors = registry.getInterceptors(advisor);
					interceptorList.addAll(Arrays.asList(interceptors));
				}
			}
            //普通方法
			else {
				Interceptor[] interceptors = registry.getInterceptors(advisor);
				interceptorList.addAll(Arrays.asList(interceptors));
			}
		}
		return interceptorList;
	}

其實這個攔截器鏈的處理和process()加起來就決定了哪些增強方法會被處理。

Cglib

public Object getProxy(ClassLoader classLoader) {
		
			Class<?> rootClass = this.advised.getTargetClass();
			

			Class<?> proxySuperClass = rootClass;
			if (ClassUtils.isCglibProxyClass(rootClass)) {
				proxySuperClass = rootClass.getSuperclass();
				Class<?>[] additionalInterfaces = rootClass.getInterfaces();
				for (Class<?> additionalInterface : additionalInterfaces) {
					this.advised.addInterface(additionalInterface);
				}
			}

			
			Enhancer enhancer = createEnhancer();
			
			enhancer.setSuperclass(proxySuperClass);
			enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));
			enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
			enhancer.setStrategy(new MemorySafeUndeclaredThrowableStrategy(UndeclaredThrowableException.class));
			enhancer.setInterceptDuringConstruction(false);
//獲取回撥
			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);

			//建立代理類
			proxy = enhancer.create();
			

			return proxy;
	}

上面程式碼一目瞭然了,基本上就是一個cglib動態代理的配置建立程式碼,我們需要想jdk部分那樣找到代理的處理部分,在cglib中是callback

getCallBack

private static class DynamicAdvisedInterceptor implements MethodInterceptor, Serializable {

		public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
			
				
				List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
				
				if (chain.isEmpty() && Modifier.isPublic(method.getModifiers())) {
					
					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;
		}

基本和jdk的流程差不多,首先建立一個攔截器鏈,然後遍歷。

至此aop的原始碼我們分析完畢,我們來做個總結吧:

1、springaop預設使用的是jdk的代理方式,如果想使用cglib,可配置<aop:aspectj-autoproxy proxy-target-class=true/>

2、這裡有必要提一提jdk的執行效能沒有cglib高,比cglib差8倍,但建立代理的效能比cglib高10倍,對於無需頻繁建立代理比較適合使用cglib模式,反之jdk模式比較適合

3、jdk和cglib都是執行時建立代理的方式