美文网首页
Advice接口

Advice接口

作者: 我会四歩篮 | 来源:发表于2018-10-29 16:18 被阅读19次

    ### 1.Advice接口

    ![image](https://note.youdao.com/yws/public/resource/97367b3fa79f9c35015806db95fdb356/xmlnote/WEBRESOURCEfe38381cd2c6ebdc59c989d230169b17/3511)

    上图为AOP中通知(Advice)接口的实现与继承关系。

    最常用的两个 BeforeAdvice 与AfterAdvice,AfterAdvice又被AfterReturnAdvice与ThrowsAdvice接口继承

    ###  2.BeforeAdvice的实现方式

    1.实现了BeforeAdvice接口要重写Before方法

    ```

    /**

      * method为被代理的方法,就是要在这个方法前面执行一些操作

      * args 为参数列表

      * target 为被代理的类的一个对象

    **/

    public void before(Method method, Object[] args, Object target) throws Throwable {

    invokeAdviceMethod(getJoinPointMatch(), null, null);

    }

    ```

    2.以AspectJMethodBeforeAdvice类为例

    before方法调用了AbstractAspectJAdvice类中的invokeAdviceMethod(getJoinPointMatch(), null, null);

    ```

    /**

    * 调用

    * @param 获取连接点信息

    * @param 返回类型

    * @param 异常

    * @return the invocation result

    * @throws Throwable in case of invocation failure

    */

    protected Object invokeAdviceMethod(JoinPointMatch jpMatch, Object returnValue, Throwable ex) throws Throwable {

    return invokeAdviceMethodWithGivenArgs(argBinding(getJoinPoint(), jpMatch, returnValue, ex));

    }

    ```

    其中第一参数连接点JoinPoint接口,就是用来将代理对象与目标对象进行连接的一个接口

    AspectJ中的切入点匹配的执行点称作连接的(JoinPoint),

    在通知方法中可以声明一个JoinPoint类型的参数。通过JoinPoint可以访问连接点的细节。

    下面简要介绍JponPoint的方法:

    ==连接点是在什么时候生成的????==

    ```

    1.java.lang.Object[] getArgs():获取连接点方法运行时的入参列表; 

    2.Signature getSignature() :获取连接点的方法签名对象; 

    3.java.lang.Object getTarget() :获取连接点所在的目标对象; 

    4.java.lang.Object getThis() :获取代理对象本身; 

    ```

    ProceedingJoinPoint继承JoinPoint子接口,它新增了两个用于执行连接点方法的方法: 

    ```

    5.java.lang.Object proceed() throws java.lang.Throwable:通过反射执行目标对象的连接点处的方法; 

    6.java.lang.Object proceed(java.lang.Object[] args) throws java.lang.Throwable:通过反射执行目标对象连接点处的方法,不过使用新的参数替换原来的参数。

    ```

    3.执行相关的函数

    ```

    protected Object invokeAdviceMethod(JoinPointMatch jpMatch, Object returnValue, Throwable ex) throws Throwable {

    return invokeAdviceMethodWithGivenArgs(argBinding(getJoinPoint(), jpMatch, returnValue, ex));

    }

    ```

    其中argBinding(getJoinPoint(), jpMatch, returnValue, ex)

    ```

    /**

    * Take the arguments at the method execution join point and output a set of arguments

    * to the advice method

    * @param jp the current JoinPoint

    * @param jpMatch the join point match that matched this execution join point

    * @param returnValue the return value from the method execution (may be null)

    * @param ex the exception thrown by the method execution (may be null)

    * @return the empty array if there are no arguments

    */

    protected Object[] argBinding(JoinPoint jp, JoinPointMatch jpMatch, Object returnValue, Throwable ex) {

    calculateArgumentBindings();

    // AMC start

    Object[] adviceInvocationArgs = new Object[this.adviceInvocationArgumentCount];

    int numBound = 0;

    if (this.joinPointArgumentIndex != -1) {

    adviceInvocationArgs[this.joinPointArgumentIndex] = jp;

    numBound++;

    }

    else if (this.joinPointStaticPartArgumentIndex != -1) {

    adviceInvocationArgs[this.joinPointStaticPartArgumentIndex] = jp.getStaticPart();

    numBound++;

    }

    if (!CollectionUtils.isEmpty(this.argumentBindings)) {

    // binding from pointcut match

    if (jpMatch != null) {

    PointcutParameter[] parameterBindings = jpMatch.getParameterBindings();

    for (PointcutParameter parameter : parameterBindings) {

    String name = parameter.getName();

    Integer index = this.argumentBindings.get(name);

    adviceInvocationArgs[index] = parameter.getBinding();

    numBound++;

    }

    }

    // binding from returning clause

    if (this.returningName != null) {

    Integer index = this.argumentBindings.get(this.returningName);

    adviceInvocationArgs[index] = returnValue;

    numBound++;

    }

    // binding from thrown exception

    if (this.throwingName != null) {

    Integer index = this.argumentBindings.get(this.throwingName);

    adviceInvocationArgs[index] = ex;

    numBound++;

    }

    }

    if (numBound != this.adviceInvocationArgumentCount) {

    throw new IllegalStateException("Required to bind " + this.adviceInvocationArgumentCount

    + " arguments, but only bound " + numBound + " (JoinPointMatch " +

    (jpMatch == null ? "was NOT" : "WAS") +

    " bound in invocation)");

    }

    ```

    最后执行

    ```

    protected Object invokeAdviceMethodWithGivenArgs(Object[] args) throws Throwable {

    Object[] actualArgs = args;

    if (this.aspectJAdviceMethod.getParameterTypes().length == 0) {

    actualArgs = null;

    }

    try {

    ReflectionUtils.makeAccessible(this.aspectJAdviceMethod);

    // TODO AopUtils.invokeJoinpointUsingReflection

    return this.aspectJAdviceMethod.invoke(this.aspectInstanceFactory.getAspectInstance(), actualArgs);

    }

    catch (IllegalArgumentException ex) {

    throw new AopInvocationException("Mismatch on arguments to advice method [" +

    this.aspectJAdviceMethod + "]; pointcut expression [" +

    this.pointcut.getPointcutExpression() + "]", ex);

    }

    catch (InvocationTargetException ex) {

    throw ex.getTargetException();

    }

    }

    ```

    相关文章

      网友评论

          本文标题:Advice接口

          本文链接:https://www.haomeiwen.com/subject/yonbtqtx.html