现在的位置: 首页 > 综合 > 正文

Spring.Net AOP的通知类型及通知链

2012年11月26日 ⁄ 综合 ⁄ 共 6608字 ⁄ 字号 评论关闭

  首先介绍AOP通知的概念。

  通知(Advice):AOP框架在某个连接点(方法)中所采取的行为。在Spring.Net的通知类型分为环绕通知、前置通知、后置通知、异常通知。这四中通知类型以及这几通知综合运用形成的通知链。

  关于各种通知类型我实现的编程方式、配置方式两种给大家介绍。这一节主要说说上述通知类型中的后三种通知,前一种通知在上一节中已经做了说明,所以不作为本节的重点了,但是几种通知的应用大致是一样的。

  本节重点分如下两部分:

  一、AOP的四种通知类型。

  二、通知链的应用

  首先还是介绍一下开发环境以及软件版本:

  VS版本:VS2008 SP1、Spring版本:1.3.0。

  一、AOP四种通知类型介绍

  1、前置通知。我理解的前置通知是在目标对象连接点执行前的通知。

  编程方式实现。这种方式主要应用了程序集Spring.Net中Spring.Aop.Framework命名空间下的ProxyFactory(代理工厂)类和Spring.Aop命名控件下的IMethodBeforeAdvice接口。

目标对象的代码如下:  

代码

1 public interface ICommand
2 {
3 void Execute();
4 }
5
6 class ServiceCommand:ICommand
7 {
8 public void Execute()
9 {
10 Console.WriteLine("ServiceCommand execute");
11 }
12 }

通知的实现代码:

代码

1 class ConsoleLoggingBeforeAdvice:IMethodBeforeAdvice
2 {
3 public void Before(MethodInfo method, object[] args, object target)
4 {
5 Console.WriteLine("Method name is :{0}", method.Name);
6 if (args != null)
7 {
8 if (args.Length > 0)
9 {
10 for (int i = 0; i < args.Length; i++)
11 {
12 Console.WriteLine(" the {0} position argments in args is {1}", i, args[i]);
13 }
14 }
15 }
16 else
17 {
18 Console.WriteLine("args is null");
19 }
20 Console.WriteLine("the type target is {0}",target.GetType().ToString());
21 }
22 }

实现代码如下:

 

 

代码

1 ProxyFactory factory = new ProxyFactory(new ServiceCommand());
2 factory.AddAdvice(new ConsoleLoggingBeforeAdvice());
3 ICommand command = (ICommand)factory.GetProxy();
4 command.Execute();

运行结果图如下:

 

  配置方式实现。配置代码如下:

 

代码

1 <objects xmlns="http://www.springframework.net" xmlns:aop="http://www.springframework.net/aop">
2 <object id="myServiceObject" type="Spring.Aop.Framework.ProxyFactoryObject">
3 <property name="Target">
4 <object type="SpringBeforeAdvice.ServiceCommand" singleton="0"></object>
5 </property>
6 <property name="InterceptorNames">
7 <list>
8 <value>beforeAdvice</value>
9 </list>
10 </property>
11 </object>
12 <object id="beforeAdvice" type="SpringBeforeAdvice.ConsoleLoggingBeforeAdvice"></object>
13 </objects>

实现代码如下:

代码

1 IApplicationContext context = ContextRegistry.GetContext();
2 ICommand command2 = (ICommand)context["myServiceObject"];
3 command2.Execute();
4 IDictionary dic = context.GetObjectsOfType(typeof(ICommand));
5 foreach (DictionaryEntry item in dic)
6 {
7 Console.WriteLine("key is :{0},value is :{1}", item.Key, item.Value);
8 }

运行结果如下图:

 

可以看到:出了运行连接点Execute执行运行的代码以外,还有通知采取的行为(Before的执行)。如果通过断点调试,可以看到在连接点执行前,Before执行了。

  2、后置通知。后置通知正好是前置通知相反,是在目标对象连接点执行后的通知。它是实现了Spring.Aop命名空间下的IAfterReturningAdvice接口。

  编程方式实现。

  目标对象的实现代码和前置通知实现方式相同,这里就不给出实现代码了。后置通知的实现代码是:

 

代码

1 class ConsoleLoggingAfterAdvice: IAfterReturningAdvice
2 {
3 public void AfterReturning(object returnValue, MethodInfo method, object[] args, object target)
4 {
5 if (returnValue != null)
6 {
7 Console.WriteLine("the type of returnValue is :{0},returnValue is {1}", returnValue.GetType().ToString(), returnValue);
8 }
9 Console.WriteLine("method name is {0}", method.Name);
10 if (args != null && args.Length > 0)
11 {
12 foreach (object obj in args)
13 {
14 Console.WriteLine(obj);
15 }
16 }
17 Console.WriteLine("the type of target is :{0},returnValue is {1}", target.GetType().ToString(), target);
18 }
19 }

使用代码:

代码

1 ICommand target = new ServiceCommand();
2 ProxyFactory factory = new ProxyFactory(target);
3 factory.AddAdvice(new ConsoleLoggingAfterAdvice());
4
5 ICommand command = (ICommand)factory.GetProxy();
6 command.Execute("test string");

运行结果如下图:

 

  配置方式实现。配置文件如下:

 

代码

1 <objects xmlns="http://www.springframework.net" xmlns:aop="http://www.springframework.net/aop">
2
3 <object id ="myServiceObject" type="Spring.Aop.Framework.ProxyFactoryObject" >
4 <property name="Target">
5 <object type="SpringAfterAdvice.ServiceCommand"></object>
6 </property>
7 <property name="InterceptorNames">
8 <list>
9 <value>afterAdvice</value>
10 </list>
11 </property>
12 </object>
13
14 <object id="afterAdvice" type="SpringAfterAdvice.ConsoleLoggingAfterAdvice" ></object>
15 </objects>

实现代码:

 

1 IApplicationContext context = ContextRegistry.GetContext();
2 ICommand command2 = (ICommand)context["myServiceObject"];
3 command2.Execute("config string");

运行结果如下图:

 

  与前置通知相反,后置通知在目标对象连接点执行后再执行。

  3、异常通知。我理解的是当目标对象的连接点执行出现异常的时候执行。异常通知是实现了Spring.Aop命名空间下的IThrowingAdvice接口。

  编程方式实现:

  异常通知实现代码如下:
 

代码

1 public void AfterThrowing(FormatException ex)
2 {
3 Console.WriteLine("异常通知执行");
4 Console.WriteLine(ex.Message);
5 }
6
7
8 public void AfterThrowing(UnauthorizedAccessException ex)
9 {
10 Console.Out.WriteLine("Advised method threw this exception : " + ex);
11 }

  使用代码如下:

 

代码

1 ICommand target = new ServiceCommand();
2 ProxyFactory factory = new ProxyFactory(target);
3 factory.AddAdvice(new AroudAdvice());
4 factory.AddAdvice(new ConsoleLoggingThrowsAdvice());
5
6 ICommand command = (ICommand)factory.GetProxy();
7 command.Execute();

 

 


 

  配置方式实现。配置文件如下:

代码

1 <objects xmlns="http://www.springframework.net" xmlns:aop="http://www.springframework.net/aop">
2
3 <object id="myServiceObject" type="Spring.Aop.Framework.ProxyFactoryObject">
4 <property name="Target">
5 <object type="SpringExceptionAdvice.ServiceCommand"></object>
6 </property>
7 <property name="InterceptorNames">
8 <list>
9 <value>aroundAdvice</value>
10 <value>exceptionAdvice</value>
11 </list>
12 </property>
13 </object>
14
15 <object id="exceptionAdvice" type="SpringExceptionAdvice.ConsoleLoggingThrowsAdvice"></object>
16 <object id="aroundAdvice" type="SpringExceptionAdvice.AroudAdvice"></object>
17 </objects>

使用代码如下:

1 IApplicationContext context = ContextRegistry.GetContext();
2 ICommand command2 = (ICommand)context["myServiceObject"];
3 command2.Execute();

运行结果如下图:

  注意:异常通知实现的IThrowsAdvice中没有任何方法。但是它的实现类中必须实现public void AfterThrowing方法。并且只有目标对象的连接点执行过程中发生异常类型与AfterThrowing方法的参数一样时,异常通知才会发生。当然,AfterThrowing可以有很多重载。

  二、通知链

  1、编程方式实现。各种通知的实现代码如下:

代码

1 //前置通知
2   class ConsoleLoggingBeforeAdvice : IMethodBeforeAdvice
3 {
4 public void Before(MethodInfo method, object[] args, object target)
5 {
6 Console.WriteLine("前置通知执行");
7 Console.WriteLine("method name is {0}",method.Name);
8 if (args != null)
9 {
10 for (int i = 0; i < args.Length; i++)
11 {
12 Console.WriteLine(" the {0} position args is :{1}", i, args[i]);
13 }
14 }
15 Console.WriteLine("type of target is :{0}", target.GetType().ToString());
16
17 }
18 }
19
20  //环绕通知
21   class ConsoleLoggingAroundAdvice:IMethodInterceptor
22 {
23 public object Invoke(IMethodInvocation invocation)
24 {
25 object obj = null;
26 Console.WriteLine("环绕通知执行");
27 try
28 {
29 obj = invocation.Proceed();
30 }
31 catch
32 {
33 Console.WriteLine("目标方法执行异常");
34 }
35 return obj;
36 }
37 }
38
39 //后置通知
40   class ConsoleLoggingAfterAdvice : IAfterReturningAdvice
41 {
42 public void AfterReturning(object returnValue, MethodInfo method, object[] args, object target)
43 {
44 Console.WriteLine("后置通知执行");
45 if (returnValue != null)
46 {
47 Console.WriteLine("returnValue is :{0}",returnValue);
48 }
49 Console.WriteLine("method name is :{0}", method.Name);
50 if (args != null)
51 {
52 for (int i = 0; i < args.Length; i++)
53 {
54 Console.WriteLine(" the {0} position args is :{1}",i,args[i]);
55 }
56 }
57 Console.WriteLine("type of target is :{0}",target.GetType().ToString());
58
59 }
60 }
61
62  //异常通知
63   class ConsoleLoggingThrowsAdvice:IThrowsAdvice
64 {
65 public void AfterThrowing(FormatException ex)
66 {
67 Console.WriteLine("发生异常通知");
68 Console.WriteLine(ex.Message);
69 }
70 }

使用代码如下:

抱歉!评论已关闭.