Spring源码分析(八)之 aop

我的其他Spring源码解析:https://blog.csdn.net/caicongyang/category_2139981.html

核心概念:

advisor 
      pointcut
          classFilter
          methodMatcher
    advice  --> mechod拦截器

整体流程:


正在创建的某个bean  --> 实例化后方法找到所有匹配的Advisor  --> 利用ProxyFactory生成代理对象
代理对下执行某个方法时  --> 依据当前调用的方法找到所有匹配的Advisor  --> 执行对应的Advice逻辑

1. cglib动态代理与jdk动态代理

核心点: 接口使用jdk ,其他使用cglib

2.@EnableAspectJAutoProxy

往bean工厂添加 AnnotationAwareAspectJAutoProxyCreator;

AnnotationAwareAspectJAutoProxyCreator 继承 AbstractAutoProxyCreator 是一个beanPostProcess 在初始化后方法postProcessAfterInitialization中判断初始中bean是否存在匹配的advice,如果存在则要生成一个ProxyFactory代理对象;

其中AnnotationAwareAspectJAutoProxyCreator 重写了findCandidateAdvisors()会找到所有的Advisor类型并从所有切面中解析@Before等注解得到Advisor对象;

3. ProxyFactory

ProxyFactory是Spring对动态代理的封装
JdkDynamicAopProxy类的invoke方法中会筛选出匹配的Advisor,并适配成Interceptor,并封装成一个责任链,在MethodInvocation类的proceed()方法中做递归调用;

CglibAopProxy也有类似的逻辑;

JdkDynamicAopProxy的invoke方法如下:

	@Override
	@Nullable
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		Object oldProxy = null;
		boolean setProxyContext = false;

		// 拿到被代理对象
		TargetSource targetSource = this.advised.targetSource;
		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]);
			}
			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...
				// 也是直接调用Advised接口中的方法,不走代理逻辑
				// 其实就是利用代理对象获取ProxyFactory中的信息
				return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
			}

			Object retVal;

			// 如果ProxyFactory的exposeProxy为true,则将代理对象设置到currentProxy这个ThreadLocal中去
			if (this.advised.exposeProxy) {
				// Make invocation available if necessary.
				oldProxy = AopContext.setCurrentProxy(proxy);
				setProxyContext = true;
			}

			// Get as late as possible to minimize the time we "own" the target,
			// in case it comes from a pool.
			// 被代理对象和代理类
			target = targetSource.getTarget();
			Class<?> targetClass = (target != null ? target.getClass() : null);

			// Get the interception chain for this method.
			// 代理对象在执行某个方法时,根据方法筛选出匹配的Advisor,并适配成Interceptor
			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.
				// 如果没有Advice,则直接调用对应方法
				Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
				retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
			}
			else {
				// We need to create a method invocation...
				MethodInvocation 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 != Object.class && 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);
			}
		}
	}

猜你喜欢

转载自blog.csdn.net/caicongyang/article/details/122994273