Spring.Net实现AOP以及AOP相关概念(学习笔记四)

本文内容纲要:Spring.Net实现AOP以及AOP相关概念(学习笔记四)

  Spring的重要应用是在AOP(Aspect- Oriented programming面向方面编程)编程方面。Spring.Net是如何进行AOP的呢?下面是我在学习Spring实现AOP的例子以及我个人的一些浅显的理解,若有不妥之处,还望大侠们指出。

  本节重点分如下两部分:

  1、Spring实现AOP。

***  2、AOP相关概念。***

  先介绍如何实现AOP,然后再通过使用过程中的用法,谈谈我自己对AOP概念的理解。

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

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

  在我使用Spring.Net实现AOP的例子中有两个部分:1、使用编程方式实现。2、使用配置方式实现。实际在应用中,应用配置实现AOP还是相对更好点。实现AOP除了之前用到的程序集以外,还需使用程序集Spring.AOP。

 *** 1、Spring实现AOP***

  先说说编程实现的方式。这种方式当然不需要配置文件。主要应用了程序集Spring.Net中Spring.Aop.Framework命名空间下的ProxyFactory(代理工厂)类。

  先给出需要进行拦截的对象的代码:

代码

1  public interface ICommand

2 {

3 object Execute(object context);

4

5 }

6 public class BusinessCommand : ICommand

7 {

8 public object Execute(object context)

9 {

10 Console.WriteLine("Service implementation is :{0}", context);

11 return context;

12 }

13

14 }

  下面是实现对 BusinessCommand拦截的实现代码:

代码

1public class ConsoleLoggingAroundAdvice : IMethodInterceptor

2 {

3 public object Invoke(IMethodInvocation invocation)

4 {

5 Console.WriteLine("Method in ConsoleLoggingAroundAdvice");

6

7 object obj = invocation.Proceed();

8 Console.WriteLine("invocation type is :{0}", invocation.GetType().ToString());

9 Console.WriteLine("Method name is {0}", invocation.Method.ToString());

10 return obj;

11 }

12 }

在上述拦截实现类中,我使用了环绕拦截。当然还有其他的拦截方式,以后会说到。我让ConsoleLoggingAroundAdvice类继承了Spring.AOP程序集下的AopAlliance.Intercept命名控件中的IMethodInterceptor,并中其中实现了接口的 object Invoke(IMethodInvocation invocation)方法。

  在这个例子中,我测试一下Spring.Net对Execute方法的拦截。使用代码如下:

代码

1            ICommand target = new BusinessCommand();

2 ProxyFactory factory = new ProxyFactory(target);

3 factory.AddAdvice(new ConsoleLoggingAroundAdvice());

4 object obj = factory.GetProxy();

5

6

7 ICommand business = (ICommand)obj;

8 Console.WriteLine(obj.GetType().ToString());

9 //ICommand command = (ICommand)factory.GetProxy();

10 business.Execute("tyb");

11 target.Execute("This is the argument");

说明:target.Execute("This is the argument");与拦截没有关系,即不会对 Execute方法进行拦截。后面我会说说为什么没有进行拦截的理解。

  输出如下图:

  从以上输出可以看到:我只是通过business.Execute("tyb")与 target.Execute("This is the argument")进行了输出。但是两条输出的执行方式是不一样的。显然后者输出的最后一条显示的结果。前者的输出结果为前5行。如果我用断点调试,则进行到ConsoleLoggingAroundAdvice中的Invoke方法。所以前一条输出了5行。为什么两条输出的结果会有这么大的差别呢?

  business、target两者都是实现了ICommand接口对象的实例,而前者是通过代理工厂(ProxyFactory)获取代理(GetProxy)的方式实现的,后者则不一样。我的理解是:

  通过factory.GetProxy()将拦截应用到了ICommand上,而target是直接通过new生成的,所以就没有将通知应用到target。

  在输出的第一行中,输出了object obj = factory.GetProxy()中obj的类型。它也可以转换为ICommand,说明它也是实现了ICommand的。那么如果我们将ICommand business = (ICommand)obj中将ICommand用实现它的类BusinessCommand类替换成BusinessCommand business = (BusinessCommand)obj,是不是就不能正常运行了呢?答案是肯定的。运行过程中跑出如下异常:

  由以上试验我们可推理:在应用拦截的对象中,拦截对象应该要实现一个接口。是不是这样呢。?我继续添加了ServiceCommand类,代码如下:

代码

1  public class ServiceCommand

2 {

3 public object Execute(object context)

4 {

5 Console.WriteLine("Service implementation is :{0}", context);

6 return context;

7 }

8 }

代码

1             ServiceCommand command2 = new ServiceCommand();

2 ProxyFactory factory2 = new ProxyFactory(command2);

3 factory2.AddAdvice(new ConsoleLoggingAroundAdvice());

4 ServiceCommand command3 = (ServiceCommand)factory2.GetProxy();

5 command3.Execute("tyb");

输出如下图:

  由以上输出,我可以得知,根本就没有进行拦截。

  注意:以上实现过程中,需要将接口申明为public类型的,即在给ProxyFactory的构造函数中给出对象的类型声明,不管是接口还是类对象,都必须是public的。

  接口为private类型时,在类型转换的时候会有如下异常:

  如果上例中的ServiceCommand未private类型的会有异常。但是和接口所抛出的不一样,有兴趣大家可以试试。

  说完了编程实现AOP,下面说说通过配置的方式实现。

  配置实现AOP。

  配置方式实现AOP通过配置的方式以及IOC容器获取对象的方式实现。在IOC容器的配置中,被拦截BusinessCommand类的定义是代理工厂对象(ProxyFactoryObject).

  配置如下:

代码

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 id="businessCommand" type="SpringAOPConfig.BusinessCommand"/>

6 </property>

7 <property name="InterceptorNames">

8 <list>

9 <value>consoleLoggingAroundAdvice</value>

10 </list>

11 </property>

12 </object>

13

14

15 <object id="consoleLoggingAroundAdvice" type="SpringAOPConfig.ConsoleLoggingAroundAdvice"/>

16

17

18 </objects>

其他接口定义以及类实现同编程实现的方式大致相同,只是在拦截类定义中,实现IMethodInterceptor接口中的Invoke(IMethodInvocation invocation)方法时,只调用了object obj = invocation.Proceed()。

  此时的使用方式如下:

代码

1      IApplicationContext context = ContextRegistry.GetContext();

2

3 //command2.Execute();

4  

5 object obj = context.GetObject("myServiceObject");

6 ICommand command = (ICommand)context.GetObject("myServiceObject");

7 command.Execute("tyb");

8

9 Console.WriteLine();

10

11 ICommand command2 = (ICommand)context["myServiceObject"];

12 command2.Execute("taoyongbo");

13 //command.Execute();

14   IDictionary dic = context.GetObjectsOfType(typeof(ICommand));

15 foreach (DictionaryEntry item in dic)

16 {

17 Console.WriteLine("key is: {0},value is :{1}", item.Key, item.Value);

18 }

  首先过容器获取定义的对象后,通过类型转换后直接使用。

  输出结果如下图:

  这样就实现了和编程方式一样的效果。问题是上述的方式只是对ICommand中的Execute方法进行了拦截,如果还要对接口中的其他方法进行拦截怎么办呢。?

  我们只需在ICommand中定义另一个方法就行了。定义如下:

1 public interface ICommand

2 {

3 object Execute(object context);

4

5 object Execute();

6 }

  这样就实现了对接口中所有方法的拦截。

  假设我们还要将拦截应用到其他的类上,那么我们该如何实现呢。?新的接口定义与被拦截类的定义和第一个没什么区别,我这里就不在给出了,大家有兴趣可以下载代码了看看就行了。我主要给出配置文件。

代码

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 id="businessCommand" type="SpringAOPConfig.BusinessCommand"/>

6 </property>

7 <property name="InterceptorNames">

8 <list>

9 <value>consoleLoggingAroundAdvice</value>

10 </list>

11 </property>

12 </object>

13

14 <object id="myServiceObject1" type="Spring.Aop.Framework.ProxyFactoryObject">

15 <property name="Target">

16 <object type="SpringAOPConfig.BusinessTest" />

17 </property>

18 <property name="InterceptorNames">

19 <list>

20 <value>consoleLoggingAroundAdvice</value>

21 </list>

22 </property>

23 </object>

24

25 <object id="consoleLoggingAroundAdvice" type="SpringAOPConfig.ConsoleLoggingAroundAdvice"/>

  由配置可以看出,新增的被拦截类的配置通前一个除了名称以外,其他都一样。

  使用方式如下:

代码

1    IApplicationContext context = ContextRegistry.GetContext();

2

3

4

5 object obj = context.GetObject("myServiceObject");

6 ICommand command = (ICommand)context.GetObject("myServiceObject");

7 command.Execute("tyb");

8 command.Execute();

9

10 Console.WriteLine();

11

12 ICommand command2 = (ICommand)context["myServiceObject"];

13 command2.Execute("taoyongbo");

14 command2.Execute();

15

16 IDictionary dic = context.GetObjectsOfType(typeof(ICommand));

17 foreach (DictionaryEntry item in dic)

18 {

19 Console.WriteLine("key is: {0},value is :{1}", item.Key, item.Value);

20 }

21

22 //IApplicationContext ctx = ContextRegistry.GetContext();

23 //BusinessCommand command = (BusinessCommand)ctx["myServiceObject"];

24 //command.Execute();

25

26 //IApplicationContext context = ContextRegistry.GetContext();

27   ITest business = (ITest)context["myServiceObject1"];

28

29 business.Fun1();

30

31 Console.Read();

运行结果如下图:

  对配置文件的几点总结:

  一、在进行拦截时,都定义为由Spring.Aop.Framework.ProxyFactoryObject来处理。

**  二、名称为Target的属性,定义为目标对象类型。**

**  三、属性为InterceptorNames的值,定义方面(Aspects)。**

  当然,通过配置方式实现AOP时,也需要将接口声明为public,以及在获取到目标代理对象的时候,只能通过接口来进行类型转换,这点和编程实现AOP是一致的。

***  2、AOP相关概念***

**  1、方面(Aspects)**:对横向分布在多个对象中的关注点所作的模块化。在企业应用中事务管理就是一个典型的横切关注点。在Spring.Net中,将方面实现为Advisor或拦截器(Interceptor)。Advisor一般是通知和切入点的组合。拦截器实际上就是指通知。Spring.Net中一般把环绕通知成为拦截器,而其他类型的通知成为通知。因为环绕通知实现的是AopAlliance.Intercept.IMethodInterceptor接口,而其他类型通知实现的是Spring.AOP命名控件下的其他接口。如ConsoleLoggingAroundAdvice

  2、连接点(joinPoint):程序过程中的一个点。如程序中的方法。如:BusinessCommand中的Execute方法。

  3、通知(Advice):AOP框架在某个连接点(方法)中所采取的行为。通知有很多类型:如环线通知、前置通知、后置通知、异常通知。如:ConsoleLoggingAroundAdvice中public object Invoke(IMethodInvocation invocation)所执行的代码

  4、切入点(PointCut):指通知的应用条件,用于确定某个通知应用到那个连接点(方法)上。AOP框架允许程序员自己定义切入点,也可以在定义中使用正则表达式定义。如:object id="myServiceObject"节点的定义

  5、引入(Introduction):向目标对象添加字段或方法的行为。Spring.Net允许为目标对象引入新的接口。如:可以利用引入让任何对象在运行期间实现IAuditable接口,以简化对象状态变化的跟踪过程。如程序中使用:factory.AddAdvice(new ConsoleLoggingAroundAdvice())将通知应用到目标对象上。

  6、目标对象(Target Object ):包办连接点的对象。也被称为被通知或被代理对象。如:BusinessCommand

  7、AOP代理(AOP Proxy):由AOP框架在将通知应用于目标对象后创建的对象。在Spring.Net中是使用IL代码在运行期创建的动态代理。如:程序中使用的object obj = factory.GetProxy()中。

  8、织入(Weaving):将方面进行组装,以创建一个目标对象。它可以在编译期间完成,也可以在运行期完成。Spring在运行时执行织入。织如是一个过程,如程序中ProxyFactory factory = new ProxyFactory(target); factory.AddAdvice(new ConsoleLoggingAroundAdvice()); object obj = factory.GetProxy();的执行。

  以上就是我对Spring.Net中AOP的理解。要什么不妥指出,还望不吝赐教!

代码下载:Spring.Net AOP DEMO

参考文档:Spring.Net框架参考手册

     http://www.cnblogs.com/GoodHelper/archive/2009/11/13/SpringNet_Aop_Concept.html

  

本文内容总结:Spring.Net实现AOP以及AOP相关概念(学习笔记四)

原文链接:https://www.cnblogs.com/tyb1222/archive/2010/12/10/1902424.html

以上是 Spring.Net实现AOP以及AOP相关概念(学习笔记四) 的全部内容, 来源链接: utcz.com/z/362825.html

回到顶部