springAOP--JDK动态代理及链式增强逻辑

1.ProxyFactory.getProxy()-获取到代理对象

public Object getProxy(ClassLoader classLoader) {
		return createAopProxy().getProxy(classLoader);
	}
//通过该方法决定使用jdk动态代理还是cglib动态代理
//1.如果目标对象实现了接口,使用jdk
//2.没有实现接口,使用cglib
//3.如果实现了接口,可以通过设置属性proxy-target-class为true强制使用cglib
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);
   }
}

2.jdk动态代理-jdkDynamicAopProxy

分析jdkDynamicAopProxy.getProxy()方法

public Object getProxy(@Nullable ClassLoader classLoader) {
   if (logger.isDebugEnabled()) {
      logger.debug("Creating JDK dynamic proxy: target source is " + this.advised.getTargetSource());
   }
    
    //2.1获取需要代理的接口数组
   Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
    //2.2查找需要代理的所有接口,查看每个接口里面是否equals方法或者hashcode方法,如果有就打个标记设为true
   findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
    //2.3创建proxy代理对象
   return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
}

2.1completeProxiedInterfaces()

该方法看着很长,其实就做了一件事情

为目标接口数组里面增加三个接口,1.springProxy接口,2.advised接口,3.decoratingProxy接口

然后返回接口数组

tatic Class<?>[] completeProxiedInterfaces(AdvisedSupport advised, boolean decoratingProxy) {
   Class<?>[] specifiedInterfaces = advised.getProxiedInterfaces();
   if (specifiedInterfaces.length == 0) {
      // No user-specified interfaces: check whether target class is an interface.
      Class<?> targetClass = advised.getTargetClass();
      if (targetClass != null) {
         if (targetClass.isInterface()) {
            advised.setInterfaces(targetClass);
         }
         else if (Proxy.isProxyClass(targetClass)) {
            advised.setInterfaces(targetClass.getInterfaces());
         }
         specifiedInterfaces = advised.getProxiedInterfaces();
      }
   }
   boolean addSpringProxy = !advised.isInterfaceProxied(SpringProxy.class);
   boolean addAdvised = !advised.isOpaque() && !advised.isInterfaceProxied(Advised.class);
   boolean addDecoratingProxy = (decoratingProxy && !advised.isInterfaceProxied(DecoratingProxy.class));
   int nonUserIfcCount = 0;
   if (addSpringProxy) {
      nonUserIfcCount++;
   }
   if (addAdvised) {
      nonUserIfcCount++;
   }
   if (addDecoratingProxy) {
      nonUserIfcCount++;
   }
   Class<?>[] proxiedInterfaces = new Class<?>[specifiedInterfaces.length + nonUserIfcCount];
   System.arraycopy(specifiedInterfaces, 0, proxiedInterfaces, 0, specifiedInterfaces.length);
   int index = specifiedInterfaces.length;
   if (addSpringProxy) {
      proxiedInterfaces[index] = SpringProxy.class;
      index++;
   }
   if (addAdvised) {
      proxiedInterfaces[index] = Advised.class;
      index++;
   }
   if (addDecoratingProxy) {
      proxiedInterfaces[index] = DecoratingProxy.class;
   }
   return proxiedInterfaces;
}

2.2 findDefinedEqualsAndHashCodeMethods()

private void findDefinedEqualsAndHashCodeMethods(Class<?>[] proxiedInterfaces) {
   for (Class<?> proxiedInterface : proxiedInterfaces) {
      Method[] methods = proxiedInterface.getDeclaredMethods();
      for (Method method : methods) {
         if (AopUtils.isEqualsMethod(method)) {
            this.equalsDefined = true;
         }
         if (AopUtils.isHashCodeMethod(method)) {
            this.hashCodeDefined = true;
         }
         if (this.equalsDefined && this.hashCodeDefined) {
            return;
         }
      }
   }
}

3.jdk动态代理的invoke方法

jdkDynamicAopProxy实现了InnovacationHandler接口

所有在jdkDynamicAopProxy一定会有对invoke方法的回调

getPaoxy().return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);



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


   TargetSource targetSource = this.advised.targetSource;
   Object target = null;

    //这里会将equals方法和hashcode方法排除出去,使得这两个方法不会被增强
   try {
      if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
         return equals(args[0]);
      }
      else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
         return hashCode();
      }
      ...
	
      Object retVal;
	 
       //表示需要暴露Proxy,一般用于一个方法内部调用了该类的另一个方法
      if (this.advised.exposeProxy) {
         oldProxy = AopContext.setCurrentProxy(proxy);
         setProxyContext = true;
      }

     
      target = targetSource.getTarget();
      Class<?> targetClass = (target != null ? target.getClass() : null);

      //3.1 获取拦截器链
      List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);

      //3.2 如果拦截器链为空
      if (chain.isEmpty()) {
         
         Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
         retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
      }
       //3.3如果拦截器链不为空
      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())) {
        
         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.1通过Advisor中的advise获取MethodInterceptor拦截器链

此方法将advisor分为了三种:1.PointcutAdvisor 通过匹配class和method,将MethodInterceptor加入list里

2.IntroductionAdvisor,通过匹配class,将MethodInterceptor加入到list里

3.其他advisor,直接获取并保存到list里

@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.
		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()) {
			if (advisor instanceof PointcutAdvisor) {
				// Add it conditionally.
				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;
	}
3.1.1获取MethodInterceptor的方法–getInterceptors()

通过advisor获得advice,如果advice是MethodInterceptor类型的直接加入

然后通过遍历adapter适配器,获得其他MethodInterceptor,比如用@Before注解得到的advice就是AspectJMethodBeforeAdvice,然后通过这一步包装成MethodInterceptor加入到list里

@Override
public MethodInterceptor[] getInterceptors(Advisor advisor) throws UnknownAdviceTypeException {
   List<MethodInterceptor> interceptors = new ArrayList<>(3);
   Advice advice = advisor.getAdvice();
   if (advice instanceof MethodInterceptor) {
      interceptors.add((MethodInterceptor) advice);
   }
   for (AdvisorAdapter adapter : this.adapters) {
      if (adapter.supportsAdvice(advice)) {
         interceptors.add(adapter.getInterceptor(advisor));
      }
   }
   if (interceptors.isEmpty()) {
      throw new UnknownAdviceTypeException(advisor.getAdvice());
   }
   return interceptors.toArray(new MethodInterceptor[0]);
}

3.2如果拦截器链为空

直接调用被代理对象的方法,表示当前方法没有被增强

Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);

3.3如果拦截器链不为空

invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
         
retVal = invocation.proceed();

创建一个MethodInvocation,然后调用methodInvocation的procee方法

补充:静态pointcut和动态pointcut,静态只需要匹配类和方法,动态多匹配一个参数

这个方法主要使用了责任链模式,使用一个索引currentInterceptorIndex来匹配,如果当前interceptor不是最后一个,

就执行增强逻辑,然后执行interceptor.invoke,在里面执行增强逻辑,然后再次调用this.proceed也就是invocaiton.proceed又回到这个方法继续执行下一个拦截器的增强逻辑

如果到了最后一个拦截器,就执行invokeJoinpoint(),也就是被代理方法本身的逻辑。

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;
      if (dm.methodMatcher.matches(this.method, this.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);
   }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值