Spring.Core IoC(一)
Spring.Core提供了基本的反转控制容器。其中要提到两个接口:IObjectFactory, IApplicationContext。IObjectFactory提供配置机制。IApplicationContext建立在IObjectFactory之上,并且加入了其他功能,如:AOP,消息资源处理,事件传播和应用层上下文。
当IApplicationContext加入了很多企业级方法时,IObjectFactory提供配置框架和基本方法。IApplicationContext是一个IObjectFactory的超集。
下面举个简单的例子看看:
我们使用Spring.Net的注入功能实现一个电影查找程序:
开始:
首先,在项目中引用Spring.Core,添加配置文件:
<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>
在Main函数中加入:
IApplicationContext ctx = ContextRegistry.GetContext();
对象定义:
加入一个MovieLister的类型:
public class MovieLister
{
private IMovieFinder _movieFinder;
public IMovieFinder MovieFinder
{
set
{
_movieFinder = value;
}
}
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));
}
}
在配置文件中编写:
…
<object name="MyMovieLister" type="Spring.Examples.MovieFinder.MovieLister, Spring.Examples.MovieFinder"></object>
…
其中要注意,name是唯一的。接下来在使用IApplicationContext引用MovieLister对象,代码如下:
MovieLister lister = (MovieLister)ctx.GetObject("MyMovieLister");
在MovieLister类型中定义了IMovieFinder,接下来我们就加入IMovieFinder和SampleMovieFinder,然后配置他们。
public interface IMovieFinder
{
list FindAll();
}
public class SimpleMovieFinder : IMovieFinder
{
private ArrayList _list = new ArrayList();
public SimpleMovieFinder()
{
InitList();
}
public void AddMovie(Movie m)
{
_list.Add(m);
}
private void InitList()
{
_list.Add(new Movie("La vita e bella", "Roberto Benigni"));
}
public IList FindAll()
{
return new ArrayList(_list);
}
}
配置文件中添加一个对象:
<object name="MyMovieFinder" type="Spring.Examples.MovieFinder.SimpleMovieFinder, Spring.Examples.MovieFinder"></object>
设置注入:
如何把MyMovieFinder注入到MovieLister中的IMovieFinder对象中,修改配置文件,在MyMovieLister中加入属性:
<object name="MyMovieLister" type="Spring.Examples.MovieFinder.MovieLister, Spring.Examples.MovieFinder">
<property name="movieFinder" ref="AnotherMovieFinder" />
</object>
在应用程序中,当MyMovieLister对象从IApplicationContext中被找到,Spring.Net IoC容器将MyMovieFinder对象注入到MovieLister对象的MovieFinder属性中。
现在来列出电影的导演:
static void Main(string[] args)
{
try
{
IApplicationContext ctx = ContextRegistry.GetContext();
MovieLister lister = (MovieLister)ctx.GetObject("MyMovieLister");
Movie[] movies = lister.MoviesDirectedBy("Roberto Benigni");
foreach (Movie movie in movies)
{
Console.WriteLine(string.Format("Movie Title = '{0}', Director = '{1}'.",
movie.Title, movie.Director));
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
Console.Read();
}
运行结果如下:
Movie Title = 'La vita e bella', Director = 'Roberto Benigni'.
构造函数注入:
现在在应用程序的配置文件中定义另一个IMovieFinder
<object name="AnotherMovieFinder" type="Spring.Examples.MovieFinder.ColonDelimitedMovieFinder, Spring.Examples.MovieFinder"></object>
ColonDelimitedMovieFinder的代码如下:
public class ColonDelimitedMovieFinder : IMovieFinder
{
private FileInfo _movieFile;
private IList _movies;
private static readonly char[] Delimeter = new char[] { ':' };
public ColonDelimitedMovieFinder(FileInfo file)
{
MovieFile = file;
}
public FileInfo MovieFile
{
get
{
return _movieFile;
}
set
{
_movieFile = value;
if (_movieFile != null && _movieFile.Exists)
{
InitList();
}
}
}
public IList FindAll()
{
return _movies;
}
private void InitList()
{
_movies = new ArrayList();
using (StreamReader reader = MovieFile.OpenText())
{
string line = null;
while ((line = reader.ReadLine()) != null)
{
string[] tuple = line.Split(Delimeter);
Movie movie = new Movie(tuple[0], tuple[1]);
_movies.Add(movie);
}
}
}
}
这时候应用程序运行
IMovieFinder finder = (IMovieFinder)ctx.GetObject("ColonDelimitedMovieFinder");
但是运行后会出现Spring.Objects.Factory.ObjectCreationException异常。因为ColonDelimitedMovieFinder没有无参数的构造函数。在配置文件中加入参数配置。
<object name="AnotherMovieFinder" type="Spring.Examples.MovieFinder.ColonDelimitedMovieFinder, Spring.Examples.MovieFinder">
<constructor-arg index="0" value="movies.txt"/>
</object>
运行结果为: