posts - 297,  comments - 1618,  trackbacks - 0
        Spring支持四种拦截类型:目标方法调用前(before),目标方法调用后(after),目标方法调用前后(around),以及目标方法抛出异常(throw)。
         最近用到spring的AOP来实现异常拦截,用到了spring的ThrowsAdvice。ThrowsAdvice是一个标示接口,我们可以在类中定义一个或多个,来捕获定义异常通知的bean抛出的异常,并在抛出异常前执行相应的方法。
        我想大家可能都在项目中有过这样的需求,想在某种异常抛出时进行一些记录操作,例如记录错误日志到数据库或日志文件中,但把这些代码分布到项目各处不但难于管理,并且代码量巨大,用Spring的AOP来实现拦截不失为一个比较好的方法。
        下面,让我们来感受一下它的魅力吧。
 1. 操作类TestBean
/**
 * Copyright 2007 GuangZhou Cotel Co. Ltd.
 * All right reserved.    
 * 测试异常拦截的bean     
 * 
@author <a href="mailto:xiexingxing1121@126.com">AmigoXie</a>
 * 
@version 1.0 
 * Creation date: 2007-7-24 - 下午08:00:37
 
*/

public class TestBean {
    
public void method1() throws Exception {
        
throw new Exception("Exception happened!");
    }


    
/**
     * 将字符串转换为整数.
     * 
@param number 需转换的字符串
     * 
@return 转换成的字符串
     * 
@throws NumberFormatException
     * 
@author <a href="mailto:xiexingxing1121@126.com">AmigoXie</a>
     * Creation date: 2007-7-24 - 下午08:05:41
     
*/

    
public int changeToNumber(String number) throws NumberFormatException {
        
//当number为空或非数字时,将抛出NumberFormatException
        int num = Integer.parseInt(number);
        
return num;
    }

}



2. 错误日志拦截类ExceptionAdvisor


import org.springframework.aop.ThrowsAdvice;
import org.springframework.aop.framework.ProxyFactory;

import java.lang.reflect.Method;

/**
 * Copyright 2007 GuangZhou Cotel Co. Ltd.
 * All right reserved.    
 * 异常拦截类.      
 * 
@author <a href="mailto:xiexingxing1121@126.com">AmigoXie</a>
 * 
@version 1.0 
 * Creation date: 2007-7-24 - 下午08:12:25
 
*/

public class ExceptionAdvisor implements ThrowsAdvice {
    
public static void main(String[] args) {
        TestBean bean 
= new TestBean();
        ProxyFactory pf 
= new ProxyFactory();
        pf.setTarget(bean);
        pf.addAdvice(
new ExceptionAdvisor());

        TestBean proxy 
= (TestBean) pf.getProxy();
        
try {
            proxy.method1();
        }
 catch (Exception ignore) {
        }

        
        
try {
            proxy.changeToNumber(
"amigo");
        }
 catch (Exception ignore) {
        }

    }


    
/**
     * 对未知异常的处理.
     * 
@param method
     * 
@param args
     * 
@param target
     * 
@param ex
     * 
@throws Throwable
     * 
@author <a href="mailto:xiexingxing1121@126.com">AmigoXie</a>
     * Creation date: 2007-7-24 - 下午03:35:02
     
*/

    
public void afterThrowing(Method method, Object[] args, Object target,
            Exception ex) 
throws Throwable {
        System.out.println(
"*************************************");
        System.out.println(
"Error happened in class: " + target.getClass().getName());
        System.out.println(
"Error happened in method: " + method.getName());
        
        
for (int i = 0; i < args.length; i++{
            System.out.println(
"arg[" + i + "]: " + args[i]);
        }

        
        System.out.println(
"Exception class: " + ex.getClass().getName());
        System.out.println(
"*************************************");
    }

    
    
/**
     * 对NullPointerException异常的处理
     * 
@param method
     * 
@param args
     * 
@param target
     * 
@param ex
     * 
@throws Throwable
     * 
@author <a href="mailto:xiexingxing1121@126.com">AmigoXie</a>
     * Creation date: 2007-7-24 - 下午01:17:35
     
*/

    
public void afterThrowing(Method method, Object[] args, Object target,
            NullPointerException ex) 
throws Throwable {
        System.out.println(
"*************************************");
        System.out.println(
"Error happened in class: " + target.getClass().getName());
        System.out.println(
"Error happened in method: " + method.getName());
        
        
for (int i = 0; i < args.length; i++{
            System.out.println(
"args[" + i + "]: " + args[i]);
        }

        
        System.out.println(
"Exception class: " + ex.getClass().getName());
        System.out.println(
"*************************************");
    }

}

     运行ExceptionAdvisor类后,结果如下:
     ************************************
     Error happened in class: TestBean
     Error happened in method: method1
     Exception class: java.lang.Exception
    *************************************
    *************************************
    Error happened in class: TestBean
    Error happened in method: changeToNumber
    arg[0]: amigo
    Exception class: java.lang.NumberFormatException
    *************************************

    在工程中,可将ExceptionAdvisor类作为bean定义,并指定要纳入其进行异常拦截的类。

posted on 2007-07-24 20:36 阿蜜果 阅读(15583) 评论(19)  编辑  收藏 所属分类: Spring


FeedBack:
# re: 用spring的AOP实现异常拦截
2007-07-25 03:17 | itkui
别的不说,看你代码就是享受。
代码非常优雅。
看一个人的代码可以看得出一个人的为人,我相信!  回复  更多评论
  
# re: 用spring的AOP实现异常拦截
2007-07-25 08:27 | dennis
@itkui
这马屁拍的也太假了吧,哈哈,玩笑

java代码是最没有个人风格的代码,经过一定训练写出来的都一样  回复  更多评论
  
# re: 用spring的AOP实现异常拦截
2007-07-25 08:38 | 刘远志
>>看一个人的代码可以看得出一个人的为人,我相信!
呵呵,现在IDE都有了source format,不就天下无贼了!  回复  更多评论
  
# re: 用spring的AOP实现异常拦截[未登录]
2007-07-25 08:48 | 阿蜜果
@itkui
嘿嘿,别拍我马屁,注释那些定义一下模版就行。
:)  回复  更多评论
  
# re: 用spring的AOP实现异常拦截
2007-07-25 09:34 | cresposhi
反正美女的代码一律欣赏之,哈哈  回复  更多评论
  
# re: 用spring的AOP实现异常拦截
2007-07-25 09:46 | kenzhang
这个问题没遇到过,先记下。谢了  回复  更多评论
  
# re: 用spring的AOP实现异常拦截
2007-07-25 09:49 | 文温
@version 1.0
这个版本号是cvs的版本号吗?
在模版中怎么设置呢?还有其它的cvs信息,比如 每次修改的备注信息也加到代码中。
我在网上查了一下,说是在代码中加上@version $Id: Exp $
就可以,我的cvs提交后确成了 @version $Id$,不知道为什么?
我的cvs是通过eclipse提交的  回复  更多评论
  
# re: 用spring的AOP实现异常拦截
2007-07-25 10:51 | 王勇
写的非常好!!!
顶一下!!!  回复  更多评论
  
# re: 用spring的AOP实现异常拦截
2007-07-25 11:24 | 一条老狗
AOP确实非常爽。
我就用 around 来处理 service 层的所有异常。
然后再重新抛出JSF的 AbortProcessingException
这样当出错时,错误消息将显示到用户当前正在操作的页面上,而不是跳转到专门的错误页面,这样用户当前的输入值将不会丢失!

代码:
public Object aroundAdvice(ProceedingJoinPoint pjp) throws Throwable {
Object retVal;
try {
retVal = pjp.proceed();
}
// 楽観的ロックエラー
catch (HibernateOptimisticLockingFailureException ex) {
showMessage(ex, SharedMessages.error.getMessage("error.com.0087"));
throw new AbortProcessingException(ex);
}
// データベース接続エラー
catch (DataAccessResourceFailureException ex) {
showMessage(ex, SharedMessages.other.getMessage("error.database.connection"));
throw new AbortProcessingException(ex);
}
// 既にAbortProcessingException
catch (AbortProcessingException ex) {
showMessage(ex, null);
throw ex;
}
// 他のエラー
catch (Exception ex) {
showMessage(ex, SharedMessages.other.getMessage("error.other"));
throw new AbortProcessingException(ex);

}
return retVal;
}  回复  更多评论
  
# re: 用spring的AOP实现异常拦截
2007-07-25 12:43 | sitinspring
值得一看.  回复  更多评论
  
# re: 用spring的AOP实现异常拦截
2007-07-26 17:07 | Thomas
呵呵,好文!
P.S. 各位是来看人的?还是来看代码的?
o(∩_∩)o...哈哈  回复  更多评论
  
# re: 用spring的AOP实现异常拦截
2007-07-26 19:55 | 阿蜜果
@all
感谢各位的关注,再此谢过!

@itkui
优雅的代码应该不止在于代码的格式,还在于编程思想,努力ing

@cresposhi
还要多提建议哦!

@一条老狗
多谢分享!

@Thomas
多谢关注,别砸场子:(

  回复  更多评论
  
# re: 用spring的AOP实现异常拦截
2007-08-06 10:13 | KATEHUDSON
用配置文件组织更好些吧  回复  更多评论
  
# re: 用spring的AOP实现异常拦截
2007-08-06 10:39 | 老虎
學習了

我現在的項目裏用了聲明式事務處理。
ThrowsAdvice確實強大

<tx:advice id="txAdviceDao" transaction-manager="transactionManager">
<!-- the transactional semantics... -->
<tx:attributes>
<!-- all methods starting with 'find' are read-only -->
<tx:method name="find*" read-only="true"/>
<!-- other methods use the default transaction settings (see below) -->
<tx:method name="update*" read-only="false" rollback-for="DataAccessException"/>
<tx:method name="insert*" read-only="false" rollback-for="DataAccessException"/>
<tx:method name="delete*" read-only="false" rollback-for="DataAccessException"/>
<!-- <tx:method name="*" read-only="false" rollback-for="DataAccessException"/> -->
</tx:attributes>
</tx:advice>

<aop:config proxy-target-class="true">
<aop:pointcut id="dao" expression="execution(* com.ge.gdc.management.dao.*.*(..))"/>
<aop:advisor pointcut-ref="dao" advice-ref="txAdviceDao"/>
</aop:config>  回复  更多评论
  
# re: 用spring的AOP实现异常拦截[未登录]
2007-08-06 12:22 | 阿蜜果
@KATEHUDSON
在项目中我当然也用的是配置文件来组织,这里只是写了个例子。

@老虎
恩,确实蛮强大  回复  更多评论
  
# re: 用spring的AOP实现异常拦截
2008-11-12 15:12 | libaiyu
@阿蜜果
直接导入jar包可能会出现一些It is indirectly referenced from required .class file 错误,刚才测试了一下,实际上需要的包如下:
spring-aop.jar
aopalliance.jar
spring-core.jar
cglib-nodep-2.1_3.jar
commons-logging.jar  回复  更多评论
  
# re: 用spring的AOP实现异常拦截[未登录]
2009-09-10 15:23 | zhangxu
@阿蜜果

贴个配置文件上来呀
  回复  更多评论
  
# re: 用spring的AOP实现异常拦截[未登录]
2010-05-20 16:28 | sysuxk
请问使用配置方法该如何实现?  回复  更多评论
  
# re: 用spring的AOP实现异常拦截[未登录]
2011-03-31 16:37 | 111
关键在于xml的配置信息,你却没放上来?。。  回复  更多评论
  

只有注册用户登录后才能发表评论。


网站导航:
 
<2007年7月>
24252627282930
1234567
891011121314
15161718192021
22232425262728
2930311234

      生活将我们磨圆,是为了让我们滚得更远——“圆”来如此。
      我的作品:
      玩转Axure RP  (2015年12月出版)
      

      Power Designer系统分析与建模实战  (2015年7月出版)
      
     Struts2+Hibernate3+Spring2   (2010年5月出版)
     

留言簿(262)

随笔分类

随笔档案

文章分类

相册

关注blog

积分与排名

  • 积分 - 2286196
  • 排名 - 3

最新评论

阅读排行榜

评论排行榜