Spring.Net从Java 的Spring 的.Net版本,基本上和Spring差不多的实现。Java社区的速度比.net要快太多,也要成熟太多,.Net社区有太多的东西要从Java社区学习,不过基于.Net的不成熟,也留下了更多的空间,创新的空间也同样存在。希望.Net也能出现Java一样近十年的辉煌,不过对于未来十年,形势很难判断,十年时间,语言,技术,架构,思想,都会有太多的变化。不过现在先踩着前辈们的脚步走一步思考一步了。
Spirng.Net是一个企业级应用程序框架。里面包括了目前比较流行的一些开发思想:依赖注入(DI,又称为IOC,Martin Fowler有一篇著名的文章里面比较详细的对此作了叙述--Inversion of Control Containers and the Dependency Injection pattern),AOP(面向方面编程)等一些主流架构思想。并且包含一个IOC容器与AOP库。
下面这个例子是Martin Fowler以及Spring.Net给出的一个例子,比较清楚的阐述了IOC的思想,以及可以对Spring.Net有个大概的了解。
列出由一位特定导演执导的电影清单。
public Movie [] MoviesDirectedBy (string director)
{
IList allMovies = _movieFinder.FindAll ();
IList movies = new ArrayList ();
foreach (Movie m in allMovies)
{
if (director.Equals (m.Director))
{
movies.Add (m);
}
}
return (Movie []) ArrayList.Adapter (movies).ToArray (typeof (Movie));
}
}
这个例子很简单,一个MovieLister类,一个MoviesDirectedBy方法,并返回一个Movie[]数组,这个数组列出指定导演执导的电影清单。MoviesDirectedBy请求_movieFinder(影片搜索者)对象返回后者所知道的所有电影,然后遍历返回的所有电影并返回要求的结果。在这里我们需要考察的是_movieFinder对象,如何将MovieLister对象与特定的_movieFinder对象联接起来是我们关心的问题。因为我们希望这个MoviesDirectedBy方法完全不依赖于电影存储方式。因此这个方法只能引用一个_movieFinder对象,而_movieFinder对象必需对FindAll方法作出反应,在这里我们定义一个接口:
{
/// <summary>Finds all of the stored movies.</summary>
/// <returns>All of the stored movies.</returns>
IList FindAll ();
}
{
private IMovieFinder _movieFinder;
public MovieLister ()
{
_movieFinder = new ColonDelimitedMovieFinder("movielist.txt");
}
…
这当然是可以的,而且实现起来也没有问题,但是如果我们把电影存储在不同的地方,Excel, Oracle 数据库中,这时我们就需要更改代码才能实现原有的功能。由于我们已经定义了IMovieFinder 类,我们可以不用修改 MoviesDirectedBy方法,但是我们仍需要通过其他途径获得合适的IMovieFinder实现类的实例。在上面的代码中,MovieLister 既依赖于IMovieFinder接口,也依赖于具体的实现类。现在我们需要找到一个方法,让MovieLister只依赖于IMovieFInder接口,而不依赖具体的实现类。这里的问题就是,如何使MovieLister在不知道_movieFinder具体实现类细节的情况下与其实例协同工作。这时候(Inversion of Control)控制反转模式就发挥了作用。
控制反转(依赖注入)
Movie Finder中的例子:目的是得到IMovieFinder 实现类的实类,Spring.net --Ioc IapplicationContext 容器可以帮我们做到这一点,以下的例子是从配制文件中得到IapplicationContext 实例。
<configuration>
<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="config://spring/objects"/>
</context>
<objects xmlns="http://www.springframework.net">
<description>An example that demonstrates simple IoC features.</description>
</objects>
</spring>
</configuration>
然后用下面的语句得到IapplicationContext的实例
{
IApplicationContext ctx = ContextRegistry.GetContext();
}
<object name="MyMovieLister"
type="Spring.Examples.MovieFinder.MovieLister, Spring.Examples.MovieFinder">
</object>
</objects>
public static void Main ()
{
IApplicationContext ctx = ContextRegistry.GetContext();
MovieLister lister = (MovieLister) ctx.GetObject ("MyMovieLister");
}
<object name="MyMovieFinder"
type="Spring.Examples.MovieFinder.SimpleMovieFinder, Spring.Examples.MovieFinder"/>
</object>
</objects>
<object name="MyMovieLister"
type="Spring.Examples.MovieFinder.MovieLister, Spring.Examples.MovieFinder">
<!-- using setter injection -->
<property name="movieFinder" ref="MyMovieFinder"/>
</object>
<object name="MyMovieFinder"
type="Spring.Examples.MovieFinder.SimpleMovieFinder, Spring.Examples.MovieFinder"/>
</object>
</objects>
public static void Main ()
{
IApplicationContext ctx = ContextRegistry.GetContext();
MovieLister lister = (MovieLister) ctx.GetObject ("MyMovieLister");
Movie[] movies = lister.MoviesDirectedBy("Roberto Benigni");
Console.WriteLine ("\nSearching for movie\n");
foreach (Movie movie in movies)
{
Console.WriteLine (
string.Format ("Movie Title = '{0}', Director = '{1}'.",
movie.Title, movie.Director));
}
Console.WriteLine ("\nMovieApp Done.\n\n");
}
这个时候我们就可以完整的实现这个方法了,并且MovieLister和MovieFinder解除耦合关系,通过配制我们可以从多个来源得到电影列表。
当然Spring.Net各IOC所包括的内容远远不止这些,需要我们更深一步的去学习与探究。