Spring中的Advice类型及其应用

http://blog.csdn.net/myyate/article/details/1822150

在Spring中,Advice都是通过Interceptor来实现的,主要有以下几种:

1. 环绕Advice:

 

//例子摘自Spring reference
public   interface  MethodInterceptor  extends  Interceptor {
      Object invoke(MethodInvocation invocation) 
throws  Throwable;
}
public   class  DebugInterceptor  implements  MethodInterceptor {

    
public  Object invoke(MethodInvocation invocation)  throws  Throwable {
        System.out.println(
" Before: invocation=[ "   +  invocation  +   " ] " );  //(1)
        Object rval 
=  invocation.proceed();
        System.out.println(
" Invocation returned " );  //(2)
        
return  rval;
    }
}

 

      环绕advice类似一个拦截器链,这个拦截器链的中心就是被拦截的方法。在程序(1)(2)我们可以加入我们自己的代码,以表示在方法执行前后我们需要干什么。invocation.proceed()方法运行指向连接点的拦截器链并返回proceed()的结果。

2. Before Advice

 

public   interface  MethodBeforeAdvice  extends  BeforeAdvice {
    
void  before(Method m, Object[] args, Object target)  throws  Throwable;
}

 

        一个更简单的通知类型是before 通知。它不需要 MethodInvocation对象,因为它只是在进入方法之前被调用。before advice的一个主要优点是它不需要调用proceed()方法,因此就不会发生 无意间运行拦截器链失败的情况。

3. After advice

 

public   interface  AfterReturningAdvice  extends  Advice {
    
void  afterReturning(Object returnValue, Method m, Object[] args, Object target)  throws  Throwable;
}

 

       一个After advice可以访问返回值(但不能进行修改),被调用方法,方法参数以及目标对象。

4.Throws Advice

 

// ThrowsAdvice 是一个空接口,起标识作用
public   interface  ThrowsAdvice  extends  Advice {

}
// 所给对象必须实现一个或者多个针对特定类型的异常通知方法,格式如下
afterThrowing([Method], [args], [target], subclassOfThrowable)
// 只有最后一个参数是必须的。因此异常通知方法对方法及参数的需求,方法的签名将从一到四个参数之间变化。

 

       最后还有一个是introduction advice,这个我想什么时候自己单独做个例子理解一下。

       做了个例子如下,想像一个用户登录场景:在登录之前,我们对其输入的用户名进行有效性检查;登录成功后,我们记上用户登录次数;如果登录失败,则进行异常处理。实现代码如下:

 

package  com.learn.spring.test.advisor;
//登录的业务代码
public   interface  LoginService {
    
void  login(String name, String password)  throws  UnauthorityException;
}

public   class  LoginServiceImpl  implements  LoginService {

    
public   void  login(String name, String password)  throws  UnauthorityException {
            check(name, password);
            System.err.println(name 
+   "  is logining system... " );
    }
    
    
private   void  check(String name, String password)  throws  UnauthorityException {
           
if ( " myyate " .equals(name)  &&   " pass " .equals(password) ) {
                     System.err.println(name 
+   "  passed check.... " );
            } 
else  {
                   
throw   new  UnauthorityException( " invalid password " );
            }
    }
}

 

 

 

//用户名检查 拦截器
public   class  LoginNameCheckInterceptor  implements  MethodBeforeAdvice {

    
public   void  before(Method method, Object[] args, Object target)  throws  Throwable {
         System.err.println(
" check user's name is valid? " );
        
if (args[ 0 ==   null   ||   "" .equals(args[ 0 ].toString().trim())) {
              
throw   new  IllegalArgumentException();
         }
    }
}

 

 

 

// 用户登录次数统计拦截器
public   class  LoginCountInterceptor  implements  AfterReturningAdvice ...{

    
public   void  afterReturning(Object returnValue, Method method, Object[] args, Object target)  throws  Throwable ...{
    System.err.println(
" Counting the login counts of  "   +  args[ 0 ]);
    }
}

 

 

 

//异常处理拦截器
public   class  ExceptionThrowInterceptor  implements  ThrowsAdvice {
    
    
public   void  afterThrowing(Method m, Object[] args, Object target, IllegalArgumentException ex)  throws  Throwable {
    System.err.println(
" Login name is wrong, exception:  "   +  ex);
    }
    
    
public   void  afterThrowing(Method m, Object[] args, Object target, UnauthorityException ex) {
       System.err.println(target.getClass() 
+   " . "   +  m.getName()  +  
           
" () throw a exception:  "   +  ex.getMessage());
    }
}

 

配置文件如下:

 

<? xml version="1.0" encoding="UTF-8" ?>
< beans  xmlns ="http://www.springframework.org/schema/beans"
    xmlns:xsi
="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:aop
="http://www.springframework.org/schema/aop"
    xmlns:tx
="http://www.springframework.org/schema/tx"
    xsi:schemaLocation
="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
           http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd
           http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd"
>

    
< bean  id ="loginServiceTarget"
        class
="com.learn.spring.test.advisor.LoginServiceImpl" />
        
    
< bean  id ="loginNameCheckInterceptor"
        class
="com.learn.spring.test.advisor.LoginNameCheckInterceptor" />
        
<!--  
    <bean id="loginCheckInterceptor"
        class="com.learn.spring.test.advisor.LoginCheckInterceptor"/>
         
-->
    
< bean  id ="loginCountInterceptor"
        class
="com.learn.spring.test.advisor.LoginCountInterceptor" />
    
< bean  id ="exceptionThrowInterceptor"
        class
="com.learn.spring.test.advisor.ExceptionThrowInterceptor" />
        
    
< bean  id ="loginService"  class ="org.springframework.aop.framework.ProxyFactoryBean" >
        
< property  name ="target" >< ref  local ="loginServiceTarget" /></ property >
        
< property  name ="proxyInterfaces" >
            
< list >
                
< value > com.learn.spring.test.advisor.LoginService </ value >
            
</ list >
        
</ property >
        
< property  name ="interceptorNames" >
            
< list >
                
< value > loginNameCheckInterceptor </ value >
                
< value > loginCountInterceptor </ value >
                
< value > exceptionThrowInterceptor </ value >
            
</ list >
        
</ property >
    
</ bean >
</ beans >

 

测试代码运行:

 

public   class  Test {

    
public   static   void  main(String[] args)  throws  Exception {
        BeanFactory bf 
=  
            BeanFactoryFactory.getBeanFactory(
" beans.xml " , Test. class );
        LoginService ls 
=  (LoginService) bf.getBean( " loginService " );
        ls.login(
" myyate " " pass " );
    }
}

 

输出结果:

 

check user's name is valid?
myyate passed check
....
myyate is logining system
...
Counting the login counts of myyate

 

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值