Advice接口

### 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接口)