java spring.net_spring.net 学习笔记之 AOP

本文介绍了如何通过Spring.Net的AOP特性来实现异常的统一处理,避免到处充斥try/catch。主要涉及Spring.Aop.IThrowsAdvice接口的使用,以及如何通过配置文件让ThrowAdvice在异常发生时提供服务,例如记录日志。示例中展示了如何定义接口、实现异常处理类以及配置文件的设置,最后展示了程序运行效果。
摘要由CSDN通过智能技术生成

通常我们对于异常的处理方式都是大同小异的,要么直接捕获并处理,要么让它抛向上一层,要么就是记录到日志里,或者发邮件提供管理员,但这样下来一个项目中便会到处充斥着 try/catch ,并且 catch 中的代码基本类似,于是我们闻到的其中难闻的坏味道。

本文将介绍如何通过 Spring.Net 的 AOP 特性实现异常的统一处理,如果我们需要在异常发生时做一些操作的话我们就必须实现 Spring.Aop.IThrowsAdvice,该接口没有任何实现方法,是一个空接口,它仅仅做为一个标记接口而存在,但实现了 IThrowsAdvice 接口的类必须定义至少一个 AfterThrowing 方法,方法的签名如下:

AfterThrowing([MethodInfo method, Object[] args, Object target], Exception subclass);

其中中括号括起来的前三个参数是可选的,返回值可以是任意数据类型。Spring.Aop.Framework.Adapter.ThrowsAdviceInterceptor 类实现对实现了 Spring.Aop.IThrowsAdvice 派生类中的方法依赖注入,其中的 ThrowsAdviceInterceptor() 方法检查 Spring.Aop.IThrowsAdvice 的派生类是否定义了至少一个异常处理方法,如果没有则抛出 ArgumentException 异常,MapAllExceptionHandlingMethods() 方法则在定义好的重载方法中查找出异常类型与最后一个参数所定义的类型中最接近的方法,而且我们不应该在其中实现了两个相同异常类型的方法,即使他们的参数数目不同,否则也将抛出 ArgumentException 异常。

[下面引用自《Spring 技术手册》第4章 P94 页中的一段话]

注意到当异常发生时, Throw Advice 的任务只是执行对应的方法,您并不能在 Throw Advice 中将异常处理掉,在 Throw Advice 执行完毕后,原告的异常仍将传播至应用程序之中, Throw Advice 并不介入应用程序的异常处理,异常处理仍旧是应用程序本身所要负责的,如果想要在 Throw Advice 处理时中止应用程序的处理流程,作法是抛出其它的异常。

接下来看个 Throws Advice 的实际例子,首先定义 IHello 接口:

f0cd6c7f9e7ae96feae062cb48f670f0.pngusingSystem;

f0cd6c7f9e7ae96feae062cb48f670f0.png

f0cd6c7f9e7ae96feae062cb48f670f0.pngnamespaceTestThrowAdvice

34031c708bfe702fe82d01ff5c6593aa.png

0be121fa5b8988fbabbbc526af3b0fc0.gifb854634c0904529d4018c4c3336be836.png{

587e34b10dcf5efbc0859b53470a2db3.pngpublicinterfaceIHello

3112b7b6526db5bc83e275260ae60525.png

f2671b7f42ce505d9bf55a7a0ca257fb.gifb854634c0904529d4018c4c3336be836.png{

587e34b10dcf5efbc0859b53470a2db3.pngvoidHello(stringname);

eec4c0236afc26744c9c4e910bc34958.png    }4fd96b3cf02f4c7b5c8964ac8167f7af.png}

接着定义一个 HelloSpeaker 类来实现 IHello 接口,并在 Hello() 方法中模拟程序发生错误时的异常抛出:

f0cd6c7f9e7ae96feae062cb48f670f0.pngusingSystem;

f0cd6c7f9e7ae96feae062cb48f670f0.png

f0cd6c7f9e7ae96feae062cb48f670f0.pngnamespaceTestThrowAdvice

34031c708bfe702fe82d01ff5c6593aa.png

0be121fa5b8988fbabbbc526af3b0fc0.gifb854634c0904529d4018c4c3336be836.png{

587e34b10dcf5efbc0859b53470a2db3.pngpublicclassHelloSpeaker : IHello

3112b7b6526db5bc83e275260ae60525.png

f2671b7f42ce505d9bf55a7a0ca257fb.gifb854634c0904529d4018c4c3336be836.png{

587e34b10dcf5efbc0859b53470a2db3.pngpublicvoidHello(stringname)

3112b7b6526db5bc83e275260ae60525.png

f2671b7f42ce505d9bf55a7a0ca257fb.gifb854634c0904529d4018c4c3336be836.png{

587e34b10dcf5efbc0859b53470a2db3.png            Console.WriteLine("Hello,"+name);

587e34b10dcf5efbc0859b53470a2db3.png//抱歉! 程序错误! 发生异常 XD587e34b10dcf5efbc0859b53470a2db3.pngthrownewException("发生异常

b854634c0904529d4018c4c3336be836.png");

eec4c0236afc26744c9c4e910bc34958.png        }eec4c0236afc26744c9c4e910bc34958.png    }4fd96b3cf02f4c7b5c8964ac8167f7af.png}f0cd6c7f9e7ae96feae062cb48f670f0.png

f0cd6c7f9e7ae96feae062cb48f670f0.png

如果您需要在应用程序抛出异常时,介入 Throw Advice 提供一些服务,例如记录一些异常信息,则可以实现 Spring.Aop.IThrowsAdvice 接口,在这个例子中我使用了 log4net 组件来实现日志的记录:

f0cd6c7f9e7ae96feae062cb48f670f0.pngusingSystem;

f0cd6c7f9e7ae96feae062cb48f670f0.pngusingSpring.Aop;

f0cd6c7f9e7ae96feae062cb48f670f0.pngusinglog4net;

f0cd6c7f9e7ae96feae062cb48f670f0.pngusinglog4net.Core;

f0cd6c7f9e7ae96feae062cb48f670f0.pngusingSystem.Reflection;

f0cd6c7f9e7ae96feae062cb48f670f0.png

f0cd6c7f9e7ae96feae062cb48f670f0.png[assembly: log4net.Config.XmlConfigurator(Watch=true)]

f0cd6c7f9e7ae96feae062cb48f670f0.pngnamespaceTestThrowAdvice

34031c708bfe702fe82d01ff5c6593aa.png

0be121fa5b8988fbabbbc526af3b0fc0.gifb854634c0904529d4018c4c3336be836.png{

587e34b10dcf5efbc0859b53470a2db3.pngpublicclassSomeThrowAdvice : IThrowsAdvice

3112b7b6526db5bc83e275260ae60525.png

f2671b7f42ce505d9bf55a7a0ca257fb.gifb854634c0904529d4018c4c3336be836.png{

587e34b10dcf5efbc0859b53470a2db3.pngprivateILog logger;

587e34b10dcf5efbc0859b53470a2db3.png

587e34b10dcf5efbc0859b53470a2db3.pngpublicSomeThrowAdvice()

3112b7b6526db5bc83e275260ae60525.png

f2671b7f42ce505d9bf55a7a0ca257fb.gifb854634c0904529d4018c4c3336be836.png{

587e34b10dcf5efbc0859b53470a2db3.png            logger=LogManager.GetLogger(this.GetType());

eec4c0236afc26744c9c4e910bc34958.png        }587e34b10dcf5efbc0859b53470a2db3.png

587e34b10dcf5efbc0859b53470a2db3.pngpublicvoidAfterThrowing(MethodInfo method, Object[] args, Object target, Exception exception)

3112b7b6526db5bc83e275260ae60525.png

f2671b7f42ce505d9bf55a7a0ca257fb.gifb854634c0904529d4018c4c3336be836.png{

587e34b10dcf5efbc0859b53470a2db3.png//记录异常587e34b10dcf5efbc0859b53470a2db3.pnglogger.Info("记录异常", exception);

eec4c0236afc26744c9c4e910bc34958.png        }eec4c0236afc26744c9c4e910bc34958.png    }4fd96b3cf02f4c7b5c8964ac8167f7af.png}

接着在配置文件(我这里使用了独立配置文件)中写下以下的定义,让 Throw Advice 在异常发生时提供记录服务:

f0cd6c7f9e7ae96feae062cb48f670f0.png<?xml  version="1.0" encoding="utf-8"?>f0cd6c7f9e7ae96feae062cb48f670f0.png         xsi:schemaLocation="http://www.springframework.net 

f0cd6c7f9e7ae96feae062cb48f670f0.png         http://www.springframework.net/xsd/spring-objects.xsd">f0cd6c7f9e7ae96feae062cb48f670f0.png

f0cd6c7f9e7ae96feae062cb48f670f0.pngf0cd6c7f9e7ae96feae062cb48f670f0.pngf0cd6c7f9e7ae96feae062cb48f670f0.png

f0cd6c7f9e7ae96feae062cb48f670f0.pngf0cd6c7f9e7ae96feae062cb48f670f0.pngf0cd6c7f9e7ae96feae062cb48f670f0.pngf0cd6c7f9e7ae96feae062cb48f670f0.pngTestThrowAdvice.IHello,TestThrowAdvicef0cd6c7f9e7ae96feae062cb48f670f0.pngf0cd6c7f9e7ae96feae062cb48f670f0.pngf0cd6c7f9e7ae96feae062cb48f670f0.pngf0cd6c7f9e7ae96feae062cb48f670f0.pngf0cd6c7f9e7ae96feae062cb48f670f0.pngf0cd6c7f9e7ae96feae062cb48f670f0.pngf0cd6c7f9e7ae96feae062cb48f670f0.pngf0cd6c7f9e7ae96feae062cb48f670f0.pngSomeThrowAdvicef0cd6c7f9e7ae96feae062cb48f670f0.pngf0cd6c7f9e7ae96feae062cb48f670f0.pngf0cd6c7f9e7ae96feae062cb48f670f0.pngf0cd6c7f9e7ae96feae062cb48f670f0.png  

f0cd6c7f9e7ae96feae062cb48f670f0.pngf0cd6c7f9e7ae96feae062cb48f670f0.png

最后剩下我们的程序入口 Main() 函数了:

f0cd6c7f9e7ae96feae062cb48f670f0.pngusingSystem;

f0cd6c7f9e7ae96feae062cb48f670f0.pngusingSpring.Context;

f0cd6c7f9e7ae96feae062cb48f670f0.pngusingSpring.Context.Support;

f0cd6c7f9e7ae96feae062cb48f670f0.png

f0cd6c7f9e7ae96feae062cb48f670f0.pngnamespaceTestThrowAdvice

34031c708bfe702fe82d01ff5c6593aa.png

0be121fa5b8988fbabbbc526af3b0fc0.gifb854634c0904529d4018c4c3336be836.png{

587e34b10dcf5efbc0859b53470a2db3.pngpublicclassProgram

3112b7b6526db5bc83e275260ae60525.png

f2671b7f42ce505d9bf55a7a0ca257fb.gifb854634c0904529d4018c4c3336be836.png{

587e34b10dcf5efbc0859b53470a2db3.pngstaticvoidMain(string[] args)

3112b7b6526db5bc83e275260ae60525.png

f2671b7f42ce505d9bf55a7a0ca257fb.gifb854634c0904529d4018c4c3336be836.png{

587e34b10dcf5efbc0859b53470a2db3.png            log4net.Config.XmlConfigurator.Configure(); 

587e34b10dcf5efbc0859b53470a2db3.png            IApplicationContext context=newXmlApplicationContext(@"../../SpringNet.xml");

587e34b10dcf5efbc0859b53470a2db3.png            IHello helloProxy=(IHello)context.GetObject("HelloProxy");

587e34b10dcf5efbc0859b53470a2db3.png

587e34b10dcf5efbc0859b53470a2db3.pngtry3112b7b6526db5bc83e275260ae60525.png

f2671b7f42ce505d9bf55a7a0ca257fb.gifb854634c0904529d4018c4c3336be836.png{

587e34b10dcf5efbc0859b53470a2db3.png                helloProxy.Hello("Justin");

eec4c0236afc26744c9c4e910bc34958.png            }587e34b10dcf5efbc0859b53470a2db3.pngcatch(Exception ex)

3112b7b6526db5bc83e275260ae60525.png

f2671b7f42ce505d9bf55a7a0ca257fb.gifb854634c0904529d4018c4c3336be836.png{

587e34b10dcf5efbc0859b53470a2db3.png//应用程序的异常处理587e34b10dcf5efbc0859b53470a2db3.pngConsole.WriteLine(ex.Message);

eec4c0236afc26744c9c4e910bc34958.png            }eec4c0236afc26744c9c4e910bc34958.png        }eec4c0236afc26744c9c4e910bc34958.png    }4fd96b3cf02f4c7b5c8964ac8167f7af.png}

程序执行结果输出:

Hello, Justin

发生异常...

日志记录中的结果:

2006-10-30 20:59:03,125 [4020] INFO  TestThrowAdvice.SomeThrowAdvice - 记录异常

System.Exception: 发生异常...

在 TestThrowAdvice.HelloSpeaker.Hello(String name) 位置 E:\..\..\SpringNetDemo\TestThrowAdvice\HelloSpeaker.cs:行号 14

在 Spring.Objects.ObjectUtils.InvokeMethod(MethodInfo method, Object instance, Object[] arguments) 位置     c:\projects\daily\Spring.Net\src\Spring\Spring.Core\Objects\ObjectUtils.cs:行号 489

在 Spring.Aop.Framework.ReflectiveMethodInvocation.InvokeJoinpoint() 。。。。。

本博客为学习交流用,凡未注明引用的均为本人作品,转载请注明出处,如有版权问题请及时通知。由于博客时间仓促,错误之处敬请谅解,有任何意见可给我留言,愿共同学习进步。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值