Spring源码解析(9)之AOP(下)

        在spring AOP源码分析上篇Spring源码解析(8)之AOP(上)_jokeMqc的博客-CSDN博客主要是分析了EnableAspectJAutoProxy注解给我们做了什么事情,然后具体分析了AnnotationAwareAspectJAutoProxyCreator做了什么事情,目前我们分析的源码可以得到,他主要是做了两件事情,第一寻找出所有的增强器,第二创建代理对象。接下来我们来分析代理对象是如何调用目标方法的。

        一、背景知识

        @EnableAspectJAutoProxy(exposeProxy = true)​ 这个东东是用来干什么的?没有配置exposeProxy 暴露代理对象的时候我们方法调用,我们在代理方法中 通过this来调用本类的方法add()方法的时候,发现add()的方法不会被拦截而我们配置了后exposeProxy的属性,我们发现可以通过:

int retVal = ((Calculate) AopContext.currentProxy()).add(numA,numB);

        调用的时候,发现了add()方法可以被拦截,原理:把这个exposeProxy设置为true,会把代理对象存放在线程变量中,AopContext.currentProxy())是从线程变量中获取代理对象(源码中分析)。

        二、应用案例与源码分析

             我们看下面的例子:

public class TulingCalculate implements Calculate {

    public int add(int numA, int numB) {
        System.out.println("执行目标方法:add");
        //System.out.println(1/0);
        return numA+numB;
    }

    public int reduce(int numA, int numB) {
        System.out.println("执行目标方法:reduce");
        return numA-numB;
    }

    public int div(int numA, int numB) {
        System.out.println("执行目标方法:div");

        return numA/numB;
    }

    public int multi(int numA, int numB) {
        System.out.println("执行目标方法:multi");

        return numA*numB;
    }

    public int mod(int numA,int numB){
        System.out.println("执行目标方法:mod");

        int retVal = ((Calculate) AopContext.currentProxy()).add(numA,numB);

        //int retVal = this.add(numA,numB);

        return retVal%numA;

        //return numA%numB;
    }
}

                当他执行的calculate.add方法时,我们按F5进到他具体的方法调用代码中:

public class TulingMainClass {

    public static void main(String[] args) {
        AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(MainConfig.class);
        Calculate calculate = (Calculate) ctx.getBean("calculate");
        int retVal = calculate.add(2,4);
        System.out.println("运算结果是:"+retVal);
        System.out.println(ctx.getBean("tulingLogAspect"));
    }
}

        2.1代码对象调用源代码分析

	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 {
			if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
				// The target does not implement the equals(Object) method itself.
				return equals(args[0]);
			}
			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;
			}

			// 获取被代理的对象
			target = targetSource.getTarget();
			if (target != null) {
				// 设置被代理对象的class
				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 {
				// 创建方法拦截器调用链条
				invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
				// 执行拦截器链
				retVal = invocation.proceed();
			}

			// 获取方法的返回值类型
			Class<?> returnType = method.getReturnType();
			if (retVal != null && retVal == target &&
					returnType != Object.class && returnType.isInstance(proxy) &&
					!RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {
				// 如果方法返回值为 this,即 return this; 则将代理对象 proxy 赋值给 retVal .
				retVal = proxy;
			}
			// 如果返回值类型为基础类型,比如 int,long 等,当返回值为 null,抛出异常
			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获取方法上的拦截器链

       其实他获取拦截器链路,大家通过自己一步步跟着源码进去分析就可以知道,其实他这里使用到了一个责任链的一个设计模式。

		public List<Object> getInterceptorsAndDynamicInterceptionAdvice(Method method, Class<?> targetClass) {
		// 从缓存中获取缓存key 第一次肯定获取不到
		MethodCacheKey cacheKey = new MethodCacheKey(method);
		// 通过cacheKey获取缓存值
		List<Object> cached = this.methodCache.get(cacheKey);
		// 从缓存中获取不到
		if (cached == null) {
			// 获取所有的拦截器
			cached = this.advisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice(
					this, method, targetClass);
			// 放入缓存
			this.methodCache.put(cacheKey, cached);
		}
		return cached;
	}


@Override
	public List<Object> getInterceptorsAndDynamicInterceptionAdvice(
			Advised config, Method method, Class<?> targetClass) {
		// 创建拦截器集合长度是增强器的长度
		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();
		
		// 遍历所有的增强器集合
		for (Advisor advisor : config.getAdvisors()) {
			//  判断增强器是不是PointcutAdvisor
			if (advisor instanceof PointcutAdvisor) {
				// 把增强器转为PointcutAdvisor
				PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor;
				// 通过方法匹配器对增强器进行匹配
				if (config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(actualClass)) {
					MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher();
					// 能够匹配
					if (MethodMatchers.matches(mm, method, actualClass, hasIntroductions)) {
						// 将增强器转换为拦截器
						MethodInterceptor[] interceptors = registry.getInterceptors(advisor);
						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.3AOP代理对象调用链路图

        

猜你喜欢

转载自blog.csdn.net/jokeMqc/article/details/121350201