spring AOP 概述(一) Advice

Advice通知

  Advice(通知)定义在连接点做什么,为切面增强织入接口。在Spring AOP中,它主要描述Spring AOP

围绕方法调用而注入的切面行为。Advice是AOP联盟定义的一个接口,具体的接口定义在org.aopalliance.aop.

Advice中。在Spring AOP的实现中,使用了这个统一接口,并通过这个接口,为AOP切面增强的织入功能做了

更多的细化和扩展,比如提供了更具体的通知类型,如BeforeAdvice、AfterAdvice、ThrowsAdvice等。作为

Spring AOP定义的接口类,具体的切面增强可以通过这些接口集成到AOP框架中去发挥作用。我们先从

BeforeAdvice开始。如下是Advice的类层级关系

  在BeforeAdvice的继承关系中,定义了为待增强的目标方法设置的前置增强接口MethodBeforeAdvice,

如下

 1 /**
 2  * Advice invoked before a method is invoked. Such advices cannot
 3  * prevent the method call proceeding, unless they throw a Throwable.
 4  *
 5  * @see AfterReturningAdvice
 6  * @see ThrowsAdvice
 7  *
 8  * @author Rod Johnson
 9  */
10 public interface MethodBeforeAdvice extends BeforeAdvice {
11 
12     /**
13      * Callback before a given method is invoked.
14      * @param method method being invoked
15      * @param args arguments to the method
16      * @param target target of the method invocation. May be {@code null}.
17      * @throws Throwable if this object wishes to abort the call.
18      * Any exception thrown will be returned to the caller if it's
19      * allowed by the method signature. Otherwise the exception
20      * will be wrapped as a runtime exception.
21      */
22     void before(Method method, Object[] args, Object target) throws Throwable;
23 
24 }

为了说明BeforeAdvice子类MethodBeforeAdvice的具体使用,来看一下子类CountingBeforeAdvice

1 public class CountingBeforeAdvice extends MethodCounter implements MethodBeforeAdvice {
2 
3     @Override
4     public void before(Method m, Object[] args, Object target) throws Throwable {
5         count(m);
6     }
7 
8 }

  

  这里调用了count方法,count方法在CountingBeforeAdvice的基类MethodCounter中实现

 1 public class MethodCounter implements Serializable {
 2 
 3     /** Method name --> count, does not understand overloading */
 4     private HashMap<String, Integer> map = new HashMap<String, Integer>();
 5 
 6     private int allCount;
 7 
 8     protected void count(Method m) {
 9         count(m.getName());
10     }
11 
12     protected void count(String methodName) {
13         Integer i = map.get(methodName);
14         i = (i != null) ? new Integer(i.intValue() + 1) : new Integer(1);
15         map.put(methodName, i);
16         ++allCount;
17     }
18

这个切面增强完成的统计实现并不复杂,它在对象中维护一个哈希表,用来存储统计数据

AfterAdvice

  在Advice的实现体系中,Spring还提供了AfterAdvice这种通知类型,以AfterReturningAdvice通知的

实现为例,分析一下AfterAdvice通知类型的实现原理

 1 public interface AfterReturningAdvice extends AfterAdvice {
 2 
 3     /**
 4      * Callback after a given method successfully returned.
 5      * @param returnValue the value returned by the method, if any
 6      * @param method method being invoked
 7      * @param args arguments to the method
 8      * @param target target of the method invocation. May be {@code null}.
 9      * @throws Throwable if this object wishes to abort the call.
10      * Any exception thrown will be returned to the caller if it's
11      * allowed by the method signature. Otherwise the exception
12      * will be wrapped as a runtime exception.
13      */
14     void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable;
15 
16 }

  afterReturning方法也是一个回调函数,AOP应用需要在这个接口实现中提供切面增强的具体设计,在

这个Advice通知被正确配置以后,在目标方法调用结束并成功返回的时候,接口会被Spring AOP回调。

与前面分析BeforeAdvice一样,同样可以看到一个CountingAfterReturningAdvice,它的实现基本上与

CountingBeforeAdvice是一样的。

  所不同的是调用发生的时间。尽管增强逻辑相同,但是,如果它实现不同的AOP通知接口,就会被AOP

编织到不同的调用场合中。尽管它们完成的增强行为是一样的,都是根据目标方法名对调用次数进行统计,

但是它们的最终实现却有很大的不同,一个是在目标方法调用前实现切面增强,一个在目标方法成功调用

返回结果后实现切面增强。由此可见,AOP技术给应用带来的灵活性,使得相同的代码完全可以根据应用

的需要灵活地出现在不同的应用场合。

ThrowsAdvice

  了解了BeforeAdvice和AfterAdvice,在Spring AOP中,还有一种ThrowsAdvice,它在抛出异常是被回调

, 可以在CountingThrowsAdvice来了解ThrowsAdvice的使用方法,如下

 1     @SuppressWarnings("serial")
 2     public static class CountingThrowsAdvice extends MethodCounter implements ThrowsAdvice {
 3 
 4         public void afterThrowing(IOException ex) throws Throwable {
 5             count(IOException.class.getName());
 6         }
 7 
 8         public void afterThrowing(UncheckedException ex) throws Throwable {
 9             count(UncheckedException.class.getName());
10         }
11 
12     }

  在afterThrowing中,从输入的异常对象中得到异常的名字并进行统计。

原文地址:https://www.cnblogs.com/toUpdating/p/9762063.html