Primavera AOP fuente núcleo JdkDynamicAopProxy

directorio de origen primavera AOP

Primavera AOP Fuente 01: Jdk proxy dinámico para la fuente subyacente
de primavera AOP Fuente 02: el ProxyFactory
primavera AOP Fuente 03: JdkDynamicAopProxy
primavera AOP Fuente 04: llamada MethodInvocation interceptor
primavera AOP Fuente 05: El DefaultAdvisorAutoProxyCreator
la primavera final de la pregunta del examen final: Cuando primavera AOP se reunió dependencias circulares
notas dirección de origen git: https: //github.com/chaitou/spring-framework-master.git

prefacio

A continuación, la unión segundo resorte AOP la fuente núcleo ProxyFactory , hay primavera AOP dinámico modo de generación de proxy 2, cuando los implementos objeto proxy la interfaz y no está obligado a utilizar la configuración cglib代理se utiliza cuando JdkDynamicAopProxyla generación de agente. A la inversa utilizado CglibAopProxypara generar el proxy. En el primer capítulo proxy dinámico para la fuente subyacente Jdk conocido, agente dinámico Jdk por getProxyla generación simultánea de un proxy, $proxyel objeto proxy al llamar al método, se callback invokemétodo. Así que para JdkDynamicAopProxy, el código más importante es el análisis getProxyy invokemétodos. En cuanto a la agente generador de código fuente subyacente, un primer artículo se ha introducido, sin más explicaciones
AopProxy

análisis de código fuente

getProxy

El siguiente código en el primer capítulo Jdk proxy dinámico para el código fuente subyacente que escribió de nuevo manualmente, y luego ir por aquí

	@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);
		// 判断接口是否又hashCode和equals方法
		findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
		// 使用JDK代理(classLoader, 接口, 当前JdkDynamicAopProxy对象:用于回调invoke和target对象方法)
		return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
	}
  1. classLoader: El cargador de clases actual
  2. proxiedInterfaces: La matriz actual de interfaces implementadas por la clase de proxy
  3. this: El objeto de la auto-generado para la clase de proxy, las propiedades del agente como h, h propiedad se utiliza para desencadenar el método de devolución de llamada h.invokemétodo para mejorada

invocar

En el principio invokeantes de que el primer punto de referencia a un objetivo, con el fin de aprovechar el tronco, sólo está interesado en el tema 普通增强, 引介增强y así se saltará el otro un capítulo aparte a explicar, por lo que se encuentran con 引介增强tal de ser el primero no pueden enredar

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]);
			}
			// hashCode处理
			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);
			}
			// 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;
			// 目标对象内部调用是无法实现增强的,如果exposeProxy设置为true,需要暴露代理
			// ThreadLocal<Object> currentProxy
			// 对象是ThreadLocal,在finally后会清除currentProxy
			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来自对象池,所以在创建代理前调用get获取target
			target = targetSource.getTarget();
			Class<?> targetClass = (target != null ? target.getClass() : null);

			// Get the interception chain for this method.
			// 1. 获取拦截器链
			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 {
				// We need to create a method invocation...
				// 2. 将拦截器统一封装成ReflectiveMethodInvocation
				MethodInvocation invocation =
						new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
				// Proceed to the joinpoint through the interceptor chain.
				// 3. 执行拦截器链
				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,释放target资源池由子类实现
				targetSource.releaseTarget(target);
			}
			if (setProxyContext) {
				// Restore old proxy.
				AopContext.setCurrentProxy(oldProxy);
			}
		}
	}

1. Obtener cadena interceptor

Este método toma toda la corriente methoda juego advice(mejora), el seguimiento getInterceptorsAndDynamicInterceptionAdvicese encuentra código para ser utilizado caché primavera AOP para mejorar el rendimiento, si el proceso se ha adquirido a través del interceptor ha podido recuperar amortiguar directamente, o mediante advisorChainFactoryla adquisición de cadena interceptor

	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;
	}

Continuar con el getInterceptorsAndDynamicInterceptionAdvicemétodo

// DefaultAdvisorChainFactory.java
public class DefaultAdvisorChainFactory implements AdvisorChainFactory, Serializable {

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

		// This is somewhat tricky... We have to process introductions first,
		// but we need to preserve order in the ultimate list.
		AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();
		Advisor[] advisors = config.getAdvisors();
		List<Object> interceptorList = new ArrayList<>(advisors.length);
		Class<?> actualClass = (targetClass != null ? targetClass : method.getDeclaringClass());
		Boolean hasIntroductions = null;

		// 循环所有切面
		for (Advisor advisor : advisors) {
			if (advisor instanceof PointcutAdvisor) {
				// Add it conditionally.
				PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor;
				// 校验当前Advisor是否适用于当前对象
				if (config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(actualClass)) {
					MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher();
					boolean match;
					// 校验Advisor是否应用到当前方法上
					if (mm instanceof IntroductionAwareMethodMatcher) {
						if (hasIntroductions == null) {
							hasIntroductions = hasMatchingIntroductions(advisors, actualClass);
						}
						match = ((IntroductionAwareMethodMatcher) mm).matches(method, actualClass, hasIntroductions);
					}
					else {
						match = mm.matches(method, actualClass);
					}
					// 匹配成功
					if (match) {
            			// 从advisor中获取拦截器数组
						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));
				}
			}
			// 其他类型的advisor
			else {
				Interceptor[] interceptors = registry.getInterceptors(advisor);
				interceptorList.addAll(Arrays.asList(interceptors));
			}
		}

		return interceptorList;
	}
	...
}

Corte transversal 引介增强, 动态增强que se preocupan 普通拦截器. El código completo es un pensamiento muy claro, obtener toda la Advisor(corte) a través de pointcutAdvisor.getPointcut().getClassFilter().matches(actualClass)partidos Asesor comprobar el objeto proxy actual, y luego por pointcutAdvisor.getPointcut().getMethodMatcher()la verificación de que coincide con la llamada actual method. Si la comprobación después extrayendo advisorel interceptorsinterceptor, añadido a interceptorListla

2. interceptor encapsula en ReflectiveMethodInvocation

Llamar a un constructor, centrándose en la siguiente llamada

	protected ReflectiveMethodInvocation(
			Object proxy, @Nullable Object target, Method method, @Nullable Object[] arguments,
			@Nullable Class<?> targetClass, List<Object> interceptorsAndDynamicMethodMatchers) {

		this.proxy = proxy;
		this.target = target;
		this.targetClass = targetClass;
		this.method = BridgeMethodResolver.findBridgedMethod(method);
		this.arguments = AopProxyUtils.adaptArgumentsIfNecessary(method, arguments);
		this.interceptorsAndDynamicMethodMatchers = interceptorsAndDynamicMethodMatchers;
	}

3. Realizar la cadena interceptor

// 执行拦截器链
retVal = invocation.proceed();
	public Object proceed() throws Throwable {
		// We start with an index of -1 and increment early.
		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;
			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);
		}
	}

Del mismo modo, sólo nos importa 普通拦截器, pero vemos 普通拦截器una sola línea de código

return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);

Esta línea de código puede hacer que los interceptores de acuerdo con el antes, después y orden definido por el usuario, incluso Orden se encadenó llamadas, esto es increíble, ¿verdad? La siguiente sección se distinguirá AspectJAfterAdvicey MethodBeforeAdviceInterceptorordenó llamado interceptor antes de la investigación es cómo mejorar y método

Publicado 42 artículos originales · ganado elogios 43 · Vistas a 40000 +

Supongo que te gusta

Origin blog.csdn.net/chaitoudaren/article/details/105278409
Recomendado
Clasificación