Spring(十八)Spring AOP createProxy 创建JDK代理 过程

上篇文章主要有以下几个主题:

  1. 围绕SpringBoot AOP加载原理。
  2. Spring AOP 是嵌入在Spring 容器启动哪个阶段。
  3. 不进行增强的原理,其中包含寻找增强器(Advisor)逻辑。

本文将围绕 创建代理过程 进行更近一步研究。

postProcessAfterInitialization

还是从Spring 容器处理器固定方法开始,AbstractAutoProxyCreator定义的 postProcessAfterInitialization ,当每个bean初始化完,都会执行这个方法:

	@Override
	public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
		if (bean != null) {
		// 获取缓存的key
			Object cacheKey = getCacheKey(bean.getClass(), beanName);
			if (this.earlyProxyReferences.remove(cacheKey) != bean) {
				return wrapIfNecessary(bean, beanName, cacheKey);
			}
		}
		return bean;
	}

上面方法,简单获取完用于缓存的key后,就进入到 wrapIfNecessary 方法进行具体包装:

	protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
	// 如果已经是 targetSourceBean了,即为增强器,那么就不进行代理,直接返回
		if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
			return bean;
		}
		// 不在advisedBeans 中
		if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
			return bean;
		}
		// 是否为框架方法以及是否没有增强器进行匹配
		if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
			this.advisedBeans.put(cacheKey, Boolean.FALSE);
			return bean;
		}

		// 获取所有过滤器
		Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
		if (specificInterceptors != DO_NOT_PROXY) {
			this.advisedBeans.put(cacheKey, Boolean.TRUE);
			// 创建代理过程
			Object proxy = createProxy(
					bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
			this.proxyTypes.put(cacheKey, proxy.getClass());
			return proxy;
		}

		this.advisedBeans.put(cacheKey, Boolean.FALSE);
		return bean;
	}

上面方法除了普通检查外,需要对两行代码具体分析。

获取所有过滤器
		Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);

		// 创建代理过程
			Object proxy = createProxy(
					bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));

getAdvicesAndAdvisorsForBean

看这个方法具体内容:

	protected Object[] getAdvicesAndAdvisorsForBean(
			Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) {
		
		List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);
		if (advisors.isEmpty()) {
			return DO_NOT_PROXY;
		}
		return advisors.toArray();
	}

findEligibleAdvisors :

	protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
		List<Advisor> candidateAdvisors = findCandidateAdvisors();
		List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
		// 是否设置在头结点设置 ExposeInvocationInterceptor 类型切点拦截器advisor
		extendAdvisors(eligibleAdvisors);
		if (!eligibleAdvisors.isEmpty()) {
			eligibleAdvisors = sortAdvisors(eligibleAdvisors);
		}
		return eligibleAdvisors;
	}

对于bean的增强,肯定有两个方面:

  1. 获取所有的增强器这在 findCandidateAdvisors 体现。
  2. 利用第一步中找到的增强器,找到该bean适用的增强器,在 findAdvisorThatCanApply
findCandidateAdvisors
	protected List<Advisor> findCandidateAdvisors() {
		// Add all the Spring advisors found according to superclass rules.
		List<Advisor> advisors = super.findCandidateAdvisors();
		// Build Advisors for all AspectJ aspects in the bean factory.
		if (this.aspectJAdvisorsBuilder != null) {
			advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
		}
		return advisors;
	}

这个方法在上一篇文章中有详细介绍,总结如下:

  1. 加载xml中配置接口,或者继承 Advisor 类的 配置接口。
  2. 使用 BeanFactoryAspectJAdvisorsBuilder 去搜寻使用 @Aspectj 注解类,并构建的 Advisor
findAdvisorsThatCanApply

上一步中,完成了所有增强器的解析,但是并不是所有都适用于当前bean,所以需要进一步过滤:

	protected List<Advisor> findAdvisorsThatCanApply(
			List<Advisor> candidateAdvisors, Class<?> beanClass, String beanName) {
			// 设置当前正在装配的beanName
		ProxyCreationContext.setCurrentProxiedBeanName(beanName);
		try {
			// 筛选出合适的Advisor
			return AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass);
		}
		finally {
			ProxyCreationContext.setCurrentProxiedBeanName(null);
		}
	}

findAdvisorsThatCanApply:

	public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> clazz) {
		if (candidateAdvisors.isEmpty()) {
			return candidateAdvisors;
		}
		List<Advisor> eligibleAdvisors = new ArrayList<>();
		// 处理 IntroductionAdvisor 类型增强器
		for (Advisor candidate : candidateAdvisors) {
			if (candidate instanceof IntroductionAdvisor && canApply(candidate, clazz)) {
				eligibleAdvisors.add(candidate);
			}
		}
		boolean hasIntroductions = !eligibleAdvisors.isEmpty();
		for (Advisor candidate : candidateAdvisors) {
			if (candidate instanceof IntroductionAdvisor) {
				// already processed
				continue;
			}
			// 对于普通bean处理
			if (canApply(candidate, clazz, hasIntroductions)) {
				eligibleAdvisors.add(candidate);
			}
		}
		return eligibleAdvisors;
	}

如何才能确定,这个bean的这些方法需要增强呢?看canApply方法:

	public static boolean canApply(Advisor advisor, Class<?> targetClass, boolean hasIntroductions) {
		if (advisor instanceof IntroductionAdvisor) {
		// IntroductionAdvisor 类型advisor
			return ((IntroductionAdvisor) advisor).getClassFilter().matches(targetClass);
		}
		else if (advisor instanceof PointcutAdvisor) {
		// 切点增强器advisor
			PointcutAdvisor pca = (PointcutAdvisor) advisor;
			return canApply(pca.getPointcut(), targetClass, hasIntroductions);
		}
		else {
			默认返回true
			return true;
		}
	}

即使用每个注解上面配置的 PointCut 注解进行匹配,匹配完后即 加入到 eligibleAdvisors 中。

createProxy

搜寻完,过滤完,即开始进入创建代理过程,入口方法为 createProxy

	protected Object createProxy(Class<?> beanClass, @Nullable String beanName,
			@Nullable Object[] specificInterceptors, TargetSource targetSource) {
		// 设置该bean的 originalTargetClass 属性
		if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
			AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);
		}
		// 定义代理工厂类
		ProxyFactory proxyFactory = new ProxyFactory();
		proxyFactory.copyFrom(this);
		// 设置代理规则,使用jdk还是cglib
		if (!proxyFactory.isProxyTargetClass()) {
			if (shouldProxyTargetClass(beanClass, beanName)) {
				proxyFactory.setProxyTargetClass(true);
			}
			else {
				evaluateProxyInterfaces(beanClass, proxyFactory);
			}
		}
		// 将上一步获取的过滤后的specificInterceptors ,转化为advisor
		Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
		// 增加 advisor增强器
		proxyFactory.addAdvisors(advisors);
		// 设置targetSource
		proxyFactory.setTargetSource(targetSource);
		customizeProxyFactory(proxyFactory);
		// 设置freezen属性,默认为false,即代理配置后,不允许修改代理值。
		proxyFactory.setFrozen(this.freezeProxy);
		if (advisorsPreFiltered()) {
			proxyFactory.setPreFiltered(true);
		}
		// 生成并获取操作。
		return proxyFactory.getProxy(getProxyClassLoader());
	}

上面即是创建代理过程,Spring将其委托给ProxyFactory处理,这里主要是对ProxyFactory进行初始化工作。

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

中间有一部创建Aop代理工厂过程:

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

DefaultAopProxyFactorycreateAopProxy 方法:

	@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.");
			}
			if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
				return new JdkDynamicAopProxy(config);
			}
			return new ObjenesisCglibAopProxy(config);
		}
		else {
			return new JdkDynamicAopProxy(config);
		}
	}

上面方法主要是判断使用何种代理:
是否 设置优化optimize,或者设置proxyTargetClass或者代理类没有接口,将影响Spring使用代理方式。

  1. 如果目标对象,实现了接口,默认情况采用jdk动态代理。
  2. 如果目标对象实现接口,可以强制使用CGLIB实现AOP。
  3. 如果没有实现接口,那么必须采用CGLIB库,Spring会自动在JDK动态代理和CGLIB之间切换。

JDK和CGLIB字节码区别:

  • JDK动态代理只能对实现接口的类生成代理,而不针对类。
  • CGLIB是针对类,实现方式为对类生成一个子类,覆盖其中方法,因为是集成,所以无法集成final方法或者类。

具体JDK和CGLIB例子可以看博主文章:

  1. jdk: https://blog.csdn.net/anLA_/article/details/77074557
  2. cglib:https://blog.csdn.net/anLA_/article/details/77074955
JdkDynamicAopProxy

对于JDK代理,有以下几个点:

  1. 继承 InvocationHandler
  2. 将代理对象传入,通过构造方法,或者普通方法。
  3. 重写invoke方法
  4. getProxy方法,获取代理后的对象
    既然创建的是代理,并且后文还会执行代理类的getProxy,所以直接看具体方法:
	@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);
		// 配置equals和hashCode接口
		findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
		// 生成代理
		return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
	}

completeProxiedInterfaces 中,主要是添加 SpringProxyAdvisedDecoratingProxy三种类型接口以及当前bean自身实现的接口bean。

代理生成完毕,接下来看 invoke方法中内容:

	@Override
	@Nullable
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
	// 用于保留旧对象
		Object oldProxy = null;
		boolean setProxyContext = false;
		// 获取targetSource
		TargetSource targetSource = this.advised.targetSource;
		Object target = null;

		try {
			if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
			// equals方法,直接执行
				// 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.
				// hashcode方法,直接执行
				return hashCode();
			}
			else if (method.getDeclaringClass() == DecoratingProxy.class) {
				// There is only getDecoratedClass() declared -> dispatch to proxy config.
				// 如果是 执行 DecoratingProxy 的几个方法,那么直接执行 
				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 的方法
				return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
			}

			Object retVal;
			// 用于处理,目标对象自我调用命中切面,需要使用此属性来暴露。
			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.
			// 获取当前方法的执行链
			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.
				Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
				retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
			}
			else {
				// 由前面的执行链路,创建一个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())) {
				// 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) {
				// 设置为原始的代理执行对象
				AopContext.setCurrentProxy(oldProxy);
			}
		}
	}

除了最开始几个if对方法类型及参数判断,主要逻辑还是在过滤器链逻辑组装处。

AOP过滤器链

对上面部分代码选出来分析:

			List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
			if (chain.isEmpty()) {
				Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
				retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
			}
			else {
				MethodInvocation invocation =
						new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
				retVal = invocation.proceed();
			}

JdkDynamicAopProxyadvised 为构造方法创建时传入,就是上面构造的 ProxyFactory 对象。
获取过滤器链操作:

	public List<Object> getInterceptorsAndDynamicInterceptionAdvice(Method method, @Nullable Class<?> targetClass) {
		MethodCacheKey cacheKey = new MethodCacheKey(method);
		List<Object> cached = this.methodCache.get(cacheKey);
		if (cached == null) {
			cached = this.advisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice(
					this, method, targetClass);
			this.methodCache.put(cacheKey, cached);
		}
		return cached;
	}

advisorChainFactory 中获取过滤器链,主要过程就是讲该方法去和过滤器链匹配,如果能够匹配,则将对应增强器返回。

MethodInvocation

当找到过滤器链后,会构造一个 ReflectiveMethodInvocation 开始执行链路。

	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 操作。
			InterceptorAndDynamicMethodMatcher dm =
					(InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
			Class<?> targetClass = (this.targetClass != null ? this.targetClass : this.method.getDeclaringClass());
			if (dm.methodMatcher.matches(this.method, targetClass, this.arguments)) {
				return dm.interceptor.invoke(this);
			}
			else {
				// Dynamic matching failed.
				// Skip this interceptor and invoke the next in the chain.
				return proceed();
			}
		}
		else {
			// It's an interceptor, so we just invoke it: The pointcut will have
			// been evaluated statically before this object was constructed.
			// 执行对应方法
			return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
		}
	}

整个执行链路可以总结为:

  1. 每当命中要拦截方法,则会获取所有advisor的执行器链。
  2. 最后进入 retVal = invocation.proceed(); 执行所有链路。
  3. 通过自带 currentInterceptorIndex 变量标识顺序,而不需要重新进入JdkDynamicAopProxy拦截
  4. 执行完后,如果有返回值,则返回对应值。

觉得博主写的有用,不妨关注博主公众号: 六点A君。
哈哈哈,一起研究Spring:
在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值