三年级短文聂耳:Spring方法拦截器MethodInterceptor

来源:百度文库 编辑:中财网 时间:2024/05/02 07:48:59
 

实现MethodInterceptor接口,在调用目标对象的方法时,就可以实现在调用方法之前、调用方法过程中、调用方法之后对其进行控制。

MethodInterceptor接口可以实现MethodBeforeAdvice接口、AfterReturningAdvice接口、ThrowsAdvice接口这三个接口能够所能够实现的功能,但是应该谨慎使用MethodInterceptor接口,很可能因为一时的疏忽忘记最重要的MethodInvocation而造成对目标对象方法调用失效,或者不能达到预期的设想。

关于含有Advice的三种对目标对象的方法的增强,可以参考文章在Spring的IOC容器中装配AOP代理

在Spring的IOC容器中装配AOP代理的基础上,比较MethodInterceptor接口的实现与上面提及到的三种接口实现对目标对象方法的增强的功能效果。

我们将从应用中分离出日志切面,,将对日志的操作整合到实现MethodInterceptor接口的类SpringMethodInterceptor中,该实现类的代码如下所示:

package org.shirdrn.spring.aop;

import java.util.Date;

import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;

public class SpringMethodInterceptor implements MethodInterceptor {

public Object invoke(MethodInvocation invo) throws Throwable {
   Object[] object = invo.getArguments();
   try{
    String date1 = (new Date()).toLocaleString();
    System.out.println("信息:[MethodInterceptor]["+date1+"]用户 "+object[0]+" 正在尝试登录陆系统...");
   
   Object returnObject = invo.proceed();
   
    String date2 = (new Date()).toLocaleString();
    System.out.println("信息:[MethodInterceptor]["+date2+"]用户 "+object[0]+" 成功登录系统.");
   
    return returnObject;
   }
   catch(Throwable throwable){
    if(object[0].equals("Jessery")){
     throw new Exception("信息:[MethodInterceptor]不允许黑名单中用户 "+object[0]+" 登录系统");
    }
   }
   return object;
}

}

程序中,红色标示的代码行Object returnObject = invo.proceed();很关键,只有通过它来对目标对象方法调用,返回一个Object对象。

调用目标对象方法之前,可以添加跟踪日志,对方法增强,相当于使用MethodBeforeAdvice接口对方法进行增强。

调用目标对象方法之后,也可以添加跟踪日志,对方法增强,相当于使用AfterReturningAdvice接口对方法进行增强。

在执行目标对象方法的过程中,如果发生异常,可以在catch中捕获异常,相当于使用ThrowsAdvice接口对方法进行增强。

上面实现了AOP,同时要在XML中装配,配置如下所示:

   class="org.shirdrn.spring.aop.SpringMethodInterceptor"
   abstract="false" singleton="true" lazy-init="default"
   autowire="default" dependency-check="default">

   class="org.springframework.aop.framework.ProxyFactoryBean"
   abstract="false" singleton="true" lazy-init="default"
   autowire="default" dependency-check="default">
  
   
  

  
   
     loginMethodBeforeAdvice
     loginAfterReturningAdvice
     loginThrowsAdvice
    springMethodInterceptor
   

  

红色标示部分为对使用MethodInterceptor对目标对象方法进行增强的配置。

测试主函数同文章在Spring的IOC容器中装配AOP代理中的相同,如下所示:

package org.shirdrn.main;

import org.shirdrn.interf.AccountServiceInterf;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Main {

public static void main(String[] args) {
   String name = "shirdrn";
   String pwd = "830119";
   ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
   AccountServiceInterf asi = (AccountServiceInterf)ctx.getBean("accountService");
   asi.login(name, pwd);
}
}

运行输出结果如下所示:

信息:[2008-3-23 17:39:38]用户 shirdrn 正在尝试登录陆系统...
信息:[MethodInterceptor][2008-3-23 17:39:39]用户 shirdrn 正在尝试登录陆系统...
信息:[MethodInterceptor][2008-3-23 17:39:42]用户 shirdrn 成功登录系统.
信息:[2008-3-23 17:39:42]用户 shirdrn 成功登录系统.

可见,标示为[MethodInterceptor]的输出信息,就是MethodInterceptor对调用目标对象方法的增强的结果。

如果我们使用非法的用户帐户登录系统:

String name = "Jessery";
   String pwd = "jessery";

就会被MethodInterceptor拦截器拦截,而且抛出异常,如下所示:

信息:[2008-3-23 17:52:18]用户 Jessery 正在尝试登录陆系统...
信息:[MethodInterceptor][2008-3-23 17:52:18]用户 Jessery 正在尝试登录陆系统...
log4j:WARN No appenders could be found for logger (org.springframework.core.CollectionFactory).
log4j:WARN Please initialize the log4j system properly.
信息:[MethodInterceptor][2008-3-23 17:52:24]用户 Jessery 登录失败.
Exception in thread "main" java.lang.reflect.UndeclaredThrowableException
at org.shirdrn.impl.AccountServiceImpl$$EnhancerByCGLIB$$32dd7c51.login()
at org.shirdrn.main.Main.main(Main.java:16)
用户登录过程中发生异常: Exception
Caused by: java.lang.Exception: 信息:[MethodInterceptor]不允许黑名单中用户 Jessery 登录系统.
at org.shirdrn.spring.aop.SpringMethodInterceptor.invoke(SpringMethodInterceptor.java:27)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:170)
at org.springframework.aop.framework.adapter.ThrowsAdviceInterceptor.invoke(ThrowsAdviceInterceptor.java:118)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:170)
at org.springframework.aop.framework.adapter.AfterReturningAdviceInterceptor.invoke(AfterReturningAdviceInterceptor.java:51)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:170)
at org.springframework.aop.framework.adapter.MethodBeforeAdviceInterceptor.invoke(MethodBeforeAdviceInterceptor.java:53)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:170)
at org.springframework.aop.framework.Cglib2AopProxy$DynamicAdvisedInterceptor.intercept(Cglib2AopProxy.java:623)
... 2 more

我们可以看到,使用MethodInterceptor拦截器打印出了三项相关信息:

调用目标对象的方法之前,对其进行了增强:

信息:[MethodInterceptor][2008-3-23 17:52:18]用户 Jessery 正在尝试登录陆系统...

因为不允许非法用户Jessery登录系统,即不允许Jessery调用login方法,故在调用login方法过程中抛出了异常,并且进行了日志跟踪:

信息:[MethodInterceptor][2008-3-23 17:52:24]用户 Jessery 登录失败.
Caused by: java.lang.Exception: 信息:[MethodInterceptor]不允许黑名单中用户 Jessery 登录系统.

总结:

使用Spring的Bean装配AOP,对于MethodBeforeAdvice接口、AfterReturningAdvice接口、ThrowsAdvice接口这三个接口在XML配置文件中配置的顺序对调用目标对象的方法没有关系。

但是如果在使用上述的基础上又使用了MethodInterceptor,如果MethodInterceptor配置顺序不同,就可能将对目标对象方法的调用进行拦截,使得我们预期设想的使用AfterReturningAdvice对方法调用之后增强失效。

因此,如果两类Advice同时使用,在装配的时候,在XML配置文件中,将MethodInterceptor的配置放在其他三种Advice的后面,使得前三种Advice先起作用,最后使用MethodInterceptor进行拦截。