【Spring 源码】AOP 的加载原理(二)

【Spring 源码】AOP 的加载原理(二)



一、选择创建策略

主要代码:DefaultAopProxyFactory#createAopProxy()

在之前讲到 DefaultAopProxyFactory 是默认的创建代理的工厂类,会根据传入的被代理类来选择不同的创建策略。

@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.");
		}
		// 如果是接口或者是 Proxy 类型的 Bean 要创建 JDK 动态代理
		if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
			return new JdkDynamicAopProxy(config);
		}

		// 其他情况会创建 CGLib 动态代理
		return new ObjenesisCglibAopProxy(config);
	}
	else {
		// 使用 JDK 动态代理
		return new JdkDynamicAopProxy(config);
	}
}

1. JDK 动态代理

JDK 动态代理

【1】获取被代理的接口

主要代码:JdkDynamicAopProxy#getProxy()

在这个过程中,主要是通过 AopProxyUtils.completeProxiedInterfaces() 进行被代理接口的筛选,在 Java 中,我们都知道一个类只能继承一个父类,但是可以实现多个接口,所以要找到被代理的接口需要做一堆工作。

@Override
public Object getProxy(@Nullable ClassLoader classLoader) {
	if (logger.isTraceEnabled()) {
		logger.trace("Creating JDK dynamic proxy: " + this.advised.getTargetSource());
	}
	
	// 获取需要代理的接口
	Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
	
	// 找 EqualsAndHashCode 方法
	findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
	
	// JDK 动态代理的获取目标类的主要方法
	return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
}

【2】JDK 动态代理主要处理方法

主要代码:JdkDynamicAopProxy#invoke()

在方法中,会发现 this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass); 这么一行方法,这边主要是使用了责任链模式对 Advisors 进行封装成链,以便后续继续使用。

@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)) {
			return equals(args[0]);
		}
		// 目标未实现 hashCode 方法
		else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
			return hashCode();
		}
		else if (method.getDeclaringClass() == DecoratingProxy.class) {
			return AopProxyUtils.ultimateTargetClass(this.advised);
		}
		// 直接反射调用
		else if (!this.advised.opaque && method.getDeclaringClass().isInterface() &&
				method.getDeclaringClass().isAssignableFrom(Advised.class)) {
			return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
		}

		Object retVal;

		if (this.advised.exposeProxy) {
			oldProxy = AopContext.setCurrentProxy(proxy);
			setProxyContext = true;
		}

		// 获取目标类
		target = targetSource.getTarget();
		Class<?> targetClass = (target != null ? target.getClass() : null);

		// 获取目标方法的拦截器调用链
		List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);

		// 如果拦截链为空,也就是当前的方法上没有任何通知并且方法访问权限还是 public 的
		if (chain.isEmpty()) {
			// 对给定的参数进行类型处理然后传入目标方法中
			Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
			retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
		}
		else {
			// 创建 ReflectiveMethodInvocation,会和 CGLib 创建的 MethodInvocation 有区别
			MethodInvocation 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())) {
			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()) {
			targetSource.releaseTarget(target);
		}
		if (setProxyContext) {
			AopContext.setCurrentProxy(oldProxy);
		}
	}
}

【3】将 Advisors 封装成调用链

主要代码:this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);

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

	// 获取注册器
	AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();
	// 获取 Advisors
	Advisor[] advisors = config.getAdvisors();
	List<Object> interceptorList = new ArrayList<>(advisors.length);
	// 获取目标类
	Class<?> actualClass = (targetClass != null ? targetClass : method.getDeclaringClass());
	Boolean hasIntroductions = null;

	// 循环 Advisors
	for (Advisor advisor : advisors) {
		// 如果 advisor 属于 PointcutAdvisor
		if (advisor instanceof PointcutAdvisor) {
			PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor;
			if (config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(actualClass)) {
				// 获取方法匹配器
				MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher();
				boolean match;
				if (mm instanceof IntroductionAwareMethodMatcher) {
					if (hasIntroductions == null) {
						hasIntroductions = hasMatchingIntroductions(advisors, actualClass);
					}
					// 判断给定的方法是否属于目标类
					match = ((IntroductionAwareMethodMatcher) mm).matches(method, actualClass, hasIntroductions);
				}
				else {
					match = mm.matches(method, actualClass);
				}
				// 如果匹配到,则需要包装成 InterceptorAndDynamicMethodMatcher 添加到责任链中
				if (match) {
					MethodInterceptor[] interceptors = registry.getInterceptors(advisor);
					if (mm.isRuntime()) {
						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;
}

【4】Advisor 的实际处理方法

主要代码:ReflectiveMethodInvocation#proceed();

proceed() 过程中会不断进行各种 Advisor 自己处理方法的调用,如果有的 Advisor 有后续处理,则会再次调用 proceed()

@Override
@Nullable
public Object proceed() throws Throwable {
	// 直接调用切入点的方法
	if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
		return invokeJoinpoint();
	}

	// 获取当前要调用的通知
	Object interceptorOrInterceptionAdvice = this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
	// 如果 Advisor 包装成了 InterceptorAndDynamicMethodMatcher,则会使用 InterceptorAndDynamicMethodMatcher 中的匹配器先进行匹配
	if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
		// 判断是否要调用通知
		InterceptorAndDynamicMethodMatcher dm = (InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
		Class<?> targetClass = (this.targetClass != null ? this.targetClass : this.method.getDeclaringClass());
		// 如果匹配成功,则会调用 InterceptorAndDynamicMethodMatcher 中注册的拦截器
		if (dm.methodMatcher.matches(this.method, targetClass, this.arguments)) {
			return dm.interceptor.invoke(this);
		}
		else {
			// 如果不需要调用当前通知,则继续查找拦截链中的其他通知
			return proceed();
		}
	}
	else {
		// 各种 Advisor 调用自己的处理方法,有的 Advisor 执行完自己的处理方法会再次调用 proceed()
		return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
	}
}

2. CGLib 动态代理

CGLib 动态代理和 JDK 动态代理的区别是 CGLib 动态代理会多一个 CallbackFilter 的处理。

【1】获取代理创建的 Bean

主要代码:CglibAopProxy#getProxy()

@Override
public Object getProxy(@Nullable ClassLoader classLoader) {
	if (logger.isTraceEnabled()) {
		logger.trace("Creating CGLIB proxy: " + this.advised.getTargetSource());
	}

	try {
		// 获取 aop 的目标类
		Class<?> rootClass = this.advised.getTargetClass();
		Assert.state(rootClass != null, "Target class must be available for creating a CGLIB proxy");

		Class<?> proxySuperClass = rootClass;
		// 判断目标类名是否带有 CGLib 自有类的特殊标志
		if (rootClass.getName().contains(ClassUtils.CGLIB_CLASS_SEPARATOR)) {
			proxySuperClass = rootClass.getSuperclass();
			Class<?>[] additionalInterfaces = rootClass.getInterfaces();
			for (Class<?> additionalInterface : additionalInterfaces) {
				this.advised.addInterface(additionalInterface);
			}
		}

		// 对类的方法进行访问权限的校验
		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 ClassLoaderAwareGeneratorStrategy(classLoader));

		// 设置动态代理回调
		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);

		// 创建被代理的目标类实例
		return createProxyClassAndInstance(enhancer, callbacks);
	}
	catch (CodeGenerationException | IllegalArgumentException ex) {
		throw new AopConfigException("Could not generate CGLIB subclass of " + this.advised.getTargetClass() + ": Common causes of this problem include using a final class or a non-visible class", ex);
	}
	catch (Throwable ex) {
		throw new AopConfigException("Unexpected AOP exception", ex);
	}
}

【3】CGLib 主要处理方法

主要代码:DynamicAdvisedInterceptor#intercept()

等待目标类以及 CGLib 创建完以后,需要等待目标类实际调用方法才会调用 intercept()。而在此方法中大部分内容和 JDK 动态代理是相同的。

@Override
@Nullable
public Object intercept(
	Object proxy, 
	Method method, 
	Object[] args, 
	MethodProxy methodProxy
) throws Throwable {
	Object oldProxy = null;
	boolean setProxyContext = false;
	Object target = null;
	TargetSource targetSource = this.advised.getTargetSource();
	try {
		if (this.advised.exposeProxy) {
			oldProxy = AopContext.setCurrentProxy(proxy);
			setProxyContext = true;
		}
		// 获取目标类
		target = targetSource.getTarget();
		Class<?> targetClass = (target != null ? target.getClass() : null);
		// 获取拦截链并对目标方法和目标类进行匹配,如果匹配成功,则会创建 InterceptorAndDynamicMethodMatcher
		List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
		Object retVal;
		// 如果拦截链为空,也就是当前的方法上没有任何通知并且方法访问权限还是 public 的
		if (chain.isEmpty() && Modifier.isPublic(method.getModifiers())) {
			// 对给定的参数进行类型处理然后传入目标方法中
			Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
			retVal = methodProxy.invoke(target, argsToUse);
		}
		else {
			// 如果目标方法上有通知,则会执行注册的通知方法,虽然和 JDK 动态代理创建的 MethodInvocation 不同,但是实际调用的和 JDK 动态代理是同一个方法
			retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();
		}
		// 对返回值进行校验
		retVal = processReturnType(proxy, target, method, retVal);
		return retVal;
	}
	finally {
		// 释放目标类
		if (target != null && !targetSource.isStatic()) {
			targetSource.releaseTarget(target);
		}
		if (setProxyContext) {
			AopContext.setCurrentProxy(oldProxy);
		}
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

瞎叨叨的一天

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值