spring.net、castle windsor、unity实现aop、ioc的方式和简单区别

本文不讲这3大框架的内部实现原理,只是提供了一个demo,分别实现了它们实现注入属性、拦截消息的例子,以写日志为例,写日志方式用异步还是同步ILogType作为写日志方式,注入日志存放地方ILogStore来演示基本的aop、ioc功能。spring.net用的1.3.1,官网http://www.springframework.net/,castle windsor用的2.5.2,官网http://www.castleproject.org/,unity用的2.0,它是微软开源项目,可在http://unity.codeplex.com/下载,该demo用的这3大框架里的依赖注入容器均为最新版本,部分配置等实现方式有细微变化,中文资料很少找,我也作为入门学习,做一个技术备份吧。

之前对spring.net熟悉点,中文资料也比较多,比如刘冬的博客http://www.cnblogs.com/GoodHelper。spring.net项目里它封装和扩展了很多其他项目,比如常用的NHibernate,windows消息队列,作业调度,asmx,wcf服务等,castle项目也是相当的庞大,monorail,activerecord,windsor,dynamicproxy等,terrylee好几年前就写过系列博文activerecord和windsor的介绍,http://www.cnblogs.com/Terrylee/archive/2006/04/28/387503.html,unity是微软企业库EntLib发展中演变出来的依赖注入容器,artech的系列文章http://www.cnblogs.com/artech/tag/Unity/  kyo-yo的系列文章 http://www.cnblogs.com/kyo-yo/tag/Entlib/等都是相当有技术含量的。

先看下整个demo的结构:

spring.net、castle windsor、unity实现aop、ioc的方式和简单区别

本程序通过写日志的方式来说明注入过程,ILogType申明写日志的方式,IlogStore申明日志存放方式: 

     ///   <summary>
    
///   http://lawson.cnblogs.com
    
///   </summary>
     public   interface  ILogType
    {
        ILogStore Logs { 
get ; set ;}
        
void  Log( string  content);
    }

 

     ///   <summary>
    
///   http://lawson.cnblogs.com
    
///   </summary>
     public   interface  ILogStore
    {
        
void  Log( string  content);
    }

 DirectLogType用来表示日志直接同步存放,ThreadLogType表示日志异步存放(这里简单处理直接new线程处理了),ConsoleLog表示日志存放控制台展现,TextLog表示日志用文本文档存放。

下面看Spring.net的代码,为了直接在Main函数看到所有代码,这里直接在Main里从容器获取对象:

Spring.net

        
static   void  Main( string [] args)
        {
            IApplicationContext ctx 
=  ContextRegistry.GetContext();

            ILogType logtype 
=  (ILogType)ctx.GetObject( " LogType " );
            
// ILogType logtype = SpringObjectManager.GetObject<ILogType>("LogType");            

            logtype.Log(
" log spring test " );

            Console.ReadKey();

        }

 

输出结果如下:

spring.net、castle windsor、unity实现aop、ioc的方式和简单区别

从代码里看不到多余的代码,它是通过配置文件注入了consoleLog,并且添加了前置后置环绕通知实现的,配置文件如下:

App.config
   < configSections >
    
< sectionGroup name = " spring " >
      
< section name = " context "  type = " Spring.Context.Support.ContextHandler, Spring.Core "   />
      
< section name = " objects "  type = " Spring.Context.Support.DefaultSectionHandler, Spring.Core "   />
    
</ sectionGroup >
  
</ configSections >

  
< spring >
    
< context >
      
< resource uri = " file://objects.xml "   />
    
</ context >
  
</ spring >

  

objects.xml
<? xml version="1.0" encoding="utf-8"  ?>
< objects  xmlns ="http://www.springframework.net"
    xmlns:xsi
="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation
="http://www.springframework.net
        http://www.springframework.net/xsd/spring-objects.xsd"
>

  
< object  id ="LogType"  type ="Common.ThreadLogType, Common"   >    <!-- singleton="false" lazy-init="false" -->
    
< property  name ="Logs"  ref ="ConsoleLog" />
  
</ object >
  
  
< object  id ="ConsoleLog"  type ="Spring.Aop.Framework.ProxyFactoryObject" >
    
< property  name ="Target" >
      
< object  type ="Common.ConsoleLog, Common" >         
      
</ object >
    
</ property >
    
< property  name ="InterceptorNames" >
      
< list >
        
< value > beforeAdvice </ value >
        
< value > aroundAdvice </ value >
        
< value > afterAdvice </ value >
        
< value > throwsAdvice </ value >
      
</ list >
    
</ property >
  
</ object >

  
< object  id ="beforeAdvice"  type ="SpringNetConsole.Advice.BeforeAdvice, SpringNetConsole"   />
  
< object  id ="aroundAdvice"  type ="SpringNetConsole.Advice.InvokeAdvice, SpringNetConsole"   />
  
< object  id ="afterAdvice"  type ="SpringNetConsole.Advice.AfterAdvice, SpringNetConsole"   />
  
< object  id ="throwsAdvice"  type ="SpringNetConsole.Advice.ExceptionAdvice, SpringNetConsole"   />


</ objects >

  

 spring.net的环绕通知通过配置后继承AopAlliance.Intercept.IMethodInterceptor接口的public object Invoke(IMethodInvocation invocation)即可拦截,前置后置通知继承Spring.Aop下的IMethodBeforeAdvice,IAfterReturningAdvice接口实现拦截,具体配置文件的说明可以查看相关文档或者spring.net专题的详细说明。

 

Castle的最新版本和以前有一定的差别,Castle.core已经封装了以前的DynamicProxy的代码,windsor在ioc方面的配置方式差不多,思路都一样的,引用其他对象,它的关键字符是$,如

 

   < component  id ="LogType"  type ="Common.ThreadLogType, Common"  service ="Common.ILogType, Common" >
    
< parameters >
      
< Logs > ${Log} </ Logs >
    
</ parameters >
  
</ component >

 

它也有自己的环绕通知和前置后置通知,环绕通知Castle.DynamicProxy.IInterceptor,前置后置通知的拦截只在一个类里Castle.DynamicProxy.StandardInterceptor。

 

Unity用起来,和官方资料看起来,感觉更希望大家通过写代码的方式注入对象和拦截对象,但是我更喜欢配置文件注入的方式,因此也用配置文件来注入对象:

 

objects.xml
<? xml version="1.0" encoding="utf-8"  ?>
< unity  xmlns ="http://schemas.microsoft.com/practices/2010/unity" >
  
< alias  alias ="singleton"  type ="Microsoft.Practices.Unity.ContainerControlledLifetimeManager, Microsoft.Practices.Unity"   />
  
< sectionExtension  type ="Microsoft.Practices.Unity.InterceptionExtension.Configuration.InterceptionConfigurationExtension,
                    Microsoft.Practices.Unity.Interception.Configuration"
  />
  
< container  name ="abc" >
    
< extension  type ="Interception"   />
    
< register  type ="IInterceptionBehavior"  mapTo ="UnityConsole.Advice.MyInterceptionBehavior,UnityConsole"  
              name
="MyInterception" ></ register >
    
< register  type ="Common.ILogType, Common"  mapTo ="Common.ThreadLogType, Common" >
      
< property  name ="Logs" >
        
< dependency  name ="regLogs" ></ dependency >
      
</ property >
    
</ register >

    
< register  name ="regLogs"  type ="Common.ILogStore, Common"  mapTo ="Common.ConsoleLog, Common" >
      
< interceptionBehavior  name ="MyInterception" />
      
< interceptor  type ="InterfaceInterceptor" />
    
</ register >
  
</ container >
</ unity >

 

具体配置方式可以查询相关文档,有意思的是我没有发现它明确的前置后置通知,只有一个通用的环绕通知拦截,Microsoft.Practices.Unity.InterceptionExtension.IInterceptionBehavior接口内的public IMethodReturn Invoke(IMethodInvocation input, GetNextInterceptionBehaviorDelegate getNext),通过注入后,继承它可以拦截到消息的执行。

但可以通过继承它的Microsoft.Practices.Unity.UnityContainerExtension扩展,完成事件的拦截,如artech的文章-IoC+AOP的简单实现http://www.cnblogs.com/artech/archive/2010/09/01/1815221.html,或者国外的http://www.machinaaurum.com.br/blog/post/AOP-With-Unity-20.aspx3篇文章,这个我也在学习中,还不是很熟。

 

这3大框架都是相当庞大的系统,需要慢慢学习,根据项目需要应用他们,也许会发现更合理更合适的实现方式。本篇博文只是简单的对3大容器完成aop、ioc的简单讲解,由于我现在对他们也是了解皮毛,文章或者程序有不对的地方,欢迎提出,我也可以多学习学习。

本demo源代码如下:

/Files/Lawson/IOCTests-lawson.rar

你可能感兴趣的:(spring)