aop 的源码分解

aop的一个例子

MockTask task = new MockTask();
ProxyFactory weaver = new ProxyFactory(task);
weaver.setInterfaces(new Class[]{ITask.class});
PrepareResourceBeforeAdvice beforeAdvice = new PrepareResourceBeforeAdvice();
ResourceCleanAfterReturningAdvice afterAdvice = new ResourceCleanAfterReturningAdvice();
weaver.addAdvice(beforeAdvice);
weaver.addAdvice(afterAdvice);
ITask proxyObject = (ITask) weaver.getProxy();
proxyObject.execute();

 

 在本示例中,ProxyFactory.getProxy  会调用  JdkDynamicAopProxy.getProxy  获取代理类。

// JdkDynamicAopProxy
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);
    findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
    return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
}

在 getProxy 中为 newProxyInstance 的 InvocationHandler 参数传入 this,即 JdkDynamicAopProxy 就是一个 InvocationHandler 的实现,其 invoke 方法如下:

// JdkDynamicAopProxy
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    // 通过advised(创建对象时初始化)获得指定的advice
    // 会将advice用相应的MethodInterceptor封装下
    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
        MethodInvocation invocation =
            new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
        // 调用procced,开始进入拦截链(执行目标对象方法和MethodInterceptor的advice)
        retVal = invocation.proceed();
    }
    return retVal;
}

首先获得指定的 advice,这里包含 beforeAdvice 和 afterAdvice 实例,但会用 MethodInterceptor 封装一层,为了后面的拦截链。

再创建一个 RelectiveMethodInvocation 对象,最后通过 proceed 进入拦截链。

RelectiveMethodInvocation 就是 Spring AOP 中 Joinpoint 的一个实现,其类图如下:

首先看下 RelectiveMethodInvocation 的构造函数:

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

做了些相关属性的赋值,然后看向 proceed 方法,如何调用目标对象和拦截器。

public Object proceed() throws Throwable {
   // currentInterceptorIndex从-1开始
   // 当达到已调用了所有的拦截器后,通过invokeJoinpoint调用目标对象的方法
   if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
      return invokeJoinpoint();
   }
   // 获得拦截器,调用其invoke方法
   // currentInterceptorIndex加1
   Object interceptorOrInterceptionAdvice =
         this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
    return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
}

currentInterceptorIndex 从 -1 开始,interceptorsAndDynamicMethodMatchers 里有两个拦截器,再由于减 1,所有调用目标对象方法的条件是currentInterceptorIndex等于 1。

首先由于 -1 != 1,会获得包含了 beforeAdvice 的MethodBeforeAdviceInterceptor 实例, currentInterceptorIndex 加 1 变为 0。调用其 invoke 方法,由于是 Before-Advice,所以先执行 beforeAdvice 的 before 方法,然后调用 proceed 进入拦截链的下一环。

// MethodBeforeAdviceInterceptor
public Object invoke(MethodInvocation mi) throws Throwable {
    this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis());
    return mi.proceed();
}

又回到了 proceed 方法,0 != 1,再次获得 advice,这次获得的是包含 afterAdvice的 AfterReturningAdviceInterceptor实例, currentInterceptorIndex 加 1 变为 1。调用其 invoke 方法,由于是 After-Returning-Adivce,所以会先执行 proceed 进入拦截链的下一环。

// AfterReturningAdviceInterceptor
public Object invoke(MethodInvocation mi) throws Throwable {
    Object retVal = mi.proceed();
    this.advice.afterReturning(retVal, mi.getMethod(), mi.getArguments(), mi.getThis());
    return retVal;
}

再次来到 proceed 方法,1 == 1,已调用完所有的拦截器,将执行目标对象的方法。然后 return 返回,回到 invoke 中,调用 afterAdvice 的 afterReturning

所以在 Joinpoint 的实现中,通过 MethodInterceptor 完成了 目标对象方法和 Advice 的先后执行。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值