springspring

springAOP源码2

2021-09-20  本文已影响0人  念䋛

上一节分析到创建代理
Object proxy = createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
createProxy方法的最后一行代码
public Object getProxy(@Nullable ClassLoader classLoader) {
return createAopProxy().getProxy(classLoader);
}
createAopProxy方法决定使用JDK代理还是Cglib代理

@Override
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
// 1.config.isProxyTargetClass()的判断
//ConfigurationClassPostProcessor#enhanceConfigurationClasses中configBeanDefs为完
//全配置类的集合(@Configuration标注的类),遍历configBeanDefs执行
//beanDef.setAttribute(AutoProxyUtils.PRESERVE_TARGET_CLASS_ATTRIBUTE, //Boolean.TRUE);代码,在AutoProxyUtils#shouldProxyTargetClass方法中获取,返回true
//返回true的话在AbstractAutoProxyCreator#createProxy 方法中执行//proxyFactory.setProxyTargetClass(true);
//简单总结当标注@Configuration类config.isProxyTargetClass()返回true
//@EnableAspectJAutoProxy(proxyTargetClass=true)所有的类都返回true
// 2.hasNoUserSuppliedProxyInterfaces 类实现了接口,实现则返回true
   if (!IN_NATIVE_IMAGE &&
         (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类
      if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
         return new JdkDynamicAopProxy(config);
      }
      return new ObjenesisCglibAopProxy(config);
   }
   else {
      return new JdkDynamicAopProxy(config);
   }
}

决定使用哪种动态代理,继续调用createAopProxy().getProxy(classLoader);
首先分析JdkDynamicAopProxy动态代理,代理很简单

@Override
public Object getProxy(@Nullable ClassLoader classLoader) {
   if (logger.isTraceEnabled()) {
      logger.trace("Creating JDK dynamic proxy: " + this.advised.getTargetSource());
   }
//JDK的动态代理,这里要注意的是入参为this,就是方法在执行的时候需要调用本类的
//(JdkDynamicAopProxy) invoke方法
   return Proxy.newProxyInstance(classLoader, this.proxiedInterfaces, this);
}

Invoke方法 分析多个Advice的调用链
Invoke的关键代码

//通过方法名称获取Advice
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
//为了调用链实例化ReflectiveMethodInvocation
MethodInvocation invocation =
      new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
// 调用链的开始
retVal = invocation.proceed();

retVal为ReflectiveMethodInvocation

@Override
@Nullable
public Object proceed() throws Throwable {
   // We start with an index of -1 and increment early.
   if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
//如果调用链结束,则调用实际的方法
      return invokeJoinpoint();
   }
// interceptorsAndDynamicMethodMatchers 要调用实际方法所要经历的拦截器集合是List //++this.currentInterceptorIndex每调用一次索引加一
   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.
//传的this,这是链路的关键, interceptorOrInterceptionAdvice的invoke都会调用
// invocation.proceed();方法,那有回调了这个方法,形成链路
      return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
   }
}

interceptorsAndDynamicMethodMatchers的集合,我们先不关心第一个,仔细看顺序,
MethodBeforeAdviceInterceptor
AspectJAfterAdvice
AspectJAfterThrowingAdvice
在以前的版本,顺序是调过来了,
AspectJAfterThrowingAdvice
AspectJAfterAdvice
MethodBeforeAdviceInterceptor
(没有实际验证过只是相关的文章),两个版本的区别,我认为老版本
AspectJAfterThrowingAdvice把所有方法都trycatch了,也就是AspectJAfterAdvice和MethodBeforeAdviceInterceptor的异常也捕获了,而这个版本,只捕获了实际调用方法的异常
[图片上传失败...(image-ee5114-1632043197037)]
MethodBeforeAdviceInterceptor

@Override
@Nullable
public Object invoke(MethodInvocation mi) throws Throwable {
//实际方法之前调用before方法
  this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis());
//上面说过,因为传的是this那mi就为ReflectiveMethodInvocation,回调了proeed方法
  return mi.proceed();
}

AspectJAfterAdvice

@Override
@Nullable
public Object invoke(MethodInvocation mi) throws Throwable {
   try {
//继续回调
     return mi.proceed();
   }
//在finally中执行后置通知
  finally {
      invokeAdviceMethod(getJoinPointMatch(), null, null);
   }
}

AspectJAfterThrowingAdvice

@Override
@Nullable
public Object invoke(MethodInvocation mi) throws Throwable {
   try {
//因为这里AspectJAfterThrowingAdvice为最后一个Advice,再执行mi.proceed()判断是最后//,就会调用实际方法,也就是AspectJAfterThrowingAdvice只捕获了实际方法的异常,是否还//AspectJAfterAdvice方法是再finally中,就算发生异常也一定会执行,
//通知当然也会执行
     return mi.proceed();
   }
   catch (Throwable ex) {
//当实际调用的方法发生异常的时候,调用invokeAdviceMethod方法,
     if (shouldInvokeOnThrowing(ex)) {
         invokeAdviceMethod(getJoinPointMatch(), null, ex);
      }
      throw ex;
   }
}

ObjenesisCglibAopProxy代理,相比较复杂一点
首先举个例子Enhancer增强类

public class MyMethodIntercpetor implements MethodInterceptor {
    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        System.out.println ("MyMethodIntercpetor拦截器---方法执行之前---拦截的是Hello的sayHello方法");
        Object invoke = methodProxy.invokeSuper (o, objects);
        System.out.println ("MyMethodIntercpetor拦截器---方法执行之后---拦截的是Hello的sayHello方法");
        return invoke;
    }
    public static void main(String[] args) {
        System.setProperty (DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "D:\\cglib");
        Enhancer enhancer = new Enhancer ();
        enhancer.setSuperclass (Hello.class);
        MyMethodIntercpetor myMethodIntercpetor = new MyMethodIntercpetor ();
        HelloMethodIntercpetor helloMethodIntercpetor = new HelloMethodIntercpetor ();
//设置callback数组是需要设置filter,调用方法时,判断使用哪个拦截器,CallbackFilter的
//accept方法返回的时数组的下角标,这是在创建代理类的时候就规定好具体使用哪个//Interceptor,
        Callback[] callback = new Callback[]{myMethodIntercpetor, helloMethodIntercpetor};
        enhancer.setCallbacks (callback);
        enhancer.setCallbackFilter (new CallbackFilterImpl ());
        //如果时单个callback不需要filter
        Hello hello = ( Hello ) enhancer.create ();
        hello.sayHello ();
    }
}
class Hello {
    public void sayHello() {
        System.out.println ("sayHello");
    }

    public void sayWorld() {
        System.out.println ("sayWorld");
    }
}
class HelloMethodIntercpetor implements MethodInterceptor {
    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        System.out.println ("HelloMethodIntercpetor拦截器---方法执行之前");
        Object invoke = methodProxy.invokeSuper (o, objects);
        System.out.println ("HelloMethodIntercpetor拦截器---方法执行之后");
        return invoke;
    }
}
class CallbackFilterImpl implements CallbackFilter {
    @Override
    public int accept(Method method) {
//因为有两个callback,当调用sayHello方法的是,return 0 会调用第一个callback,这是再增强类的时候就已经定好了,而不是再调用sayHello方法的时候,在到这里判断调用那个callback
       if (method.getName ().equals ("sayHello")) {
            return 0;
        } else {
            return 1;
        }
    }
}

那ObjenesisCglibAopProxy的getProxy方法也是类似的

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

   try {
      Class<?> rootClass = this.advised.getTargetClass();
      Assert.state(rootClass != null, "Target class must be available for creating a CGLIB proxy");
//因为rootClass可能是被@Configuration标注,就是本身已经是增强类了,这里我们获取了原始类
      Class<?> proxySuperClass = rootClass;
      if (rootClass.getName().contains(ClassUtils.CGLIB_CLASS_SEPARATOR)) {
         proxySuperClass = rootClass.getSuperclass();
         Class<?>[] additionalInterfaces = rootClass.getInterfaces();
         for (Class<?> additionalInterface : additionalInterfaces) {
            this.advised.addInterface(additionalInterface);
         }
      }

      // Validate the class, writing log messages as necessary.
      validateClassIfNecessary(proxySuperClass, classLoader);

      // Configure 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));
//获取了callbacks,这里我们只关注数组的第一个Callback DynamicAdvisedInterceptor
//因为在下面的setCallbackFilter方法中,都返回了0,其余的我也没有研究过
//也就是实际要调用的方法,都会走DynamicAdvisedInterceptor的intercept方法
      Callback[] callbacks = getCallbacks(rootClass);
      Class<?>[] types = new Class<?>[callbacks.length];
      for (int x = 0; x < types.length; x++) {
         types[x] = callbacks[x].getClass();
      }
      // fixedInterceptorMap only populated at this point, after getCallbacks call above
      enhancer.setCallbackFilter(new ProxyCallbackFilter(
            this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset));
      enhancer.setCallbackTypes(types);

      // Generate the proxy class and create a proxy instance.
      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) {
      // TargetSource.getTarget() failed
      throw new AopConfigException("Unexpected AOP exception", ex);
   }
}

DynamicAdvisedInterceptor的intercept方法和Jdk动态代理是一样的,利用调用链完成拦截功能.
Intercept方法
主要方法,就是下面的方法

retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();

点进去proceed方法,发现了supper.proceed()再点进去发现依然调用的是
ReflectiveMethodInvocation的proceed方法,就和上面介绍的jdk动态代理执行调用链一致了,这里就不介绍了.

上一篇 下一篇

猜你喜欢

热点阅读