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类关系图

《spring源码阅读(2)-aop之源码解析篇》

可以看出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的类关系图

《spring源码阅读(2)-aop之源码解析篇》

从上图可知,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都是运行时创建代理的方式

    原文作者:Spring Cloud
    原文地址: https://blog.csdn.net/cygodwg/article/details/83211495
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞