Spring AOP 拦截器Advice 的知识整理

在Spring AOP 组件中,拦截器分为两种类型,即 Advice 和 Advisor。

  Advice 有四种类型: 前置通知(before advice ) ; 后置通知(after advice ) ; 环绕通知(around advice);异常通知(exception advice)。

Spring AOP编程的核心是通过 IoC生成代理对象,代理对象的配置通常有如下属性:

<bean id="customersServiceProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
             <property name="interfaces"> <list><value>bookone.service.CustomerService</value></list></property>
            <property name="targetName"><value>customerServiceImpl</value></property>
             <property name="interceptorNames">
                      <list>
                          <value>logbefore</value>
                          <value>logafter</value>
                          <value>logaround</value>
                          <value>logthrows</value>
                      </list>  
               </property>
           </bean>

其中interfaces是目标对象所实现的接口,targetName是目标对象的名字,interceptorNames是Advice和Advisor。

  1. 前置通知(before advice)
    前置通知需要实现MethodBeforeAdvice接口,并覆盖其方法:void before(Method method,Object[] args,Object target).该方法在目标对象的方法调用前被调用。其中method是被调用的方法,args是该方法的参数,target是被调用的实例。前置通知不会阻拦目标对象方法的执行,除非前置通知中抛出了未处理的异常,否则前置通知执行后,总会执行目标对象的方法。使用前置通知,需要创建前置通知类,实现methodBeforeAdvice接口,代码如下:
public class LogBeforeAdvice implements MethodBeforeAdvice {


    public void before(Method arg0, Object[] arg1, Object arg2) throws Throwable {
         System.out.println("Invoke LogBeforeAdvice.before");
         Logger.log(arg0.getName()); //调用了Logger类的log方法,实现了日志功能。

    }

}
  1. 后置通知(after advice)
    与前置通知相对应的,Spring AOP组件提供了后置通知类型。后置通知在一个方法被调用后开始执行。创建后置通知的实现类必须先实现接口AfterReturningAdvice,并覆盖其方法:void afterReturning(Object returnValue,Method method,Object[] args,Object target).
    afterReturning方法与前置接口的before方法类似,只是多了一个返回值参数returnValue。在afterReturning方法中能访问被拦截方法的返回值,但是不能修改这个返回值。
    后置通知的实现类代码如下:
public class LogAfterAdvice implements AfterReturningAdvice {

    public void afterReturning(Object arg0, Method arg1, Object[] arg2, Object arg3) throws Throwable {
        // TODO Auto-generated method stub
            System.out.println("Invoke LogAfterAdvice.afterReturning");
            Logger.log("LogAfterAdvice : " + arg1.getName() +"return"+arg0);
    }

}

重写了afterReturning方法,该方法将在被拦截方法被调用后执行,将被拦截方法的名字和返回值写到日志文件里。

  1. 环绕通知(around advice)
    环绕通知可以在被拦截的方法执行过程的任何一个阶段被执行,也可能由于某种原因,而不调用被拦截的方法。这是前置和后置通知所做不到的。前置和后置通知无法阻止被拦截的方法被调用。环绕通知必须实现MethodInterceptor接口,覆盖接口中的方法: object invoke(MethodInvocation invocation)。
    invoke方法的参数类型是MethodInvocation,该参数类型提供了proceed方法,用来调用被拦截的方法,如果环绕通知中没有调用proceed方法,那么目标方法将不会被调用。环绕通知的实现类如下:
public class LogAroundAdvice implements MethodInterceptor {

    public Object invoke(MethodInvocation arg0) throws Throwable {
        Method method = arg0.getMethod();
        if(!method.getName().equals("viewAll")){
            System.out.println("Invoke LogAroundAdvice.invoke");
            Logger.log("LogAroundAdvice :" + method.getName());
            return arg0.proceed();
        }else{
        return null;
        }
    }

}

上述代码中,在invoke方法中首先通过调用MethodInvocation的getMethod方法返回被拦截的方法,再通过getName方法得到被拦截方法的名字。如果这个方法的名字不是“viewAll”,那么就在日志文件中记录方法名字,并通过proceed调用执行该方法。;而如果方法的名字是“viewAll”,那么它将被拦截,不被调用,也就是说环绕通知阻止了被拦截方法的调用。

4.异常通知(Exception advice)
异常通知在被拦截的方法抛出异常时调用。异常通知必须实现ThrowsAdvice接口。该接口中没有方法,是一个标记接口。实现该接口后,异常通知可以定义多个方法,方法必须符合如下规范: afterThrowing([Method], [args], [target], Throwable subclass) 。其中[Method], [args], [target]都是可选项,只有Throwable是必须指定的,即抛出异常的具体类型必须指定。异常通知的实现类如下所示:

public class LogThrowsAdvice implements ThrowsAdvice {
    public void afterThrowing(RemoteException e){
        System.out.println("Invoke LogThrowsAdvice.afterThrowing");
        Logger.log("LogThrowsAdvice : "+ e.getMessage());
    }
    public void afterThrowing(IOException e){
        Logger.log(e.getMessage());
    }

}

上述异常通知中定义了两个方法,方法中指定了不同异常类型的形式参数,分别处理RemoteException和IOException 。当被拦截的方法抛出了对应类型的异常后,将被异常通知类拦截。

这就是Spring框架中AOP组件的四种常用的Advice类型。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值