依赖注入是控制反转的一种实例,也叫反射,运行时从配置文件字符
深度理解依赖注入
作者:
EagleFish(邢瑜琨)来源:
博客园发布时间: 2009-03-13 11:01阅读: 72138 次推荐: 11
原文链接
[收藏]
摘要:提到依赖注入,大家都会想到老马那篇经典的文章。其实,本文就是相当于对那篇文章的解读。所以,如果您对原文已经有了非常深刻的理解,完全不需要再看此文;但是,如果您和笔者一样,以前曾经看过,似乎看懂了,但似乎又没抓到什么要领,不妨看看笔者这个解读,也许对您理解原文有一定帮助。
[1]
依赖在哪里
[2] DI的实现方式 [3] Setter Injection [4] 除了DI,还有Service Locator 1.依赖在哪里
1
/*
服务的接口
*/
2 public interface MovieFinder { 3 ArrayListfindAll(); 4 } 5 6 服务的消费者 7 class MovieLister 8 9 Movie[]moviesDirectedBy(Stringarg) 10 ListallMovies = finder.findAll(); 11 for (Iteratorit allMovies.iterator();it.hasNext();) 12 Moviemovie (Movie)it.next(); 13 if ( ! movie.getDirector().equals(arg))it.remove(); 14 15 return (Movie[])allMovies.toArray( new Movie[allMovies.size()]); 16 17 18 消费者内部包含一个将指向具体服务类型的实体对象 19 private MovieFinderfinder; 20 消费者需要在某一个时刻去实例化具体的服务。这是我们要解耦的关键所在, 21 *因为这样的处理方式造成了服务消费者和服务提供者的强耦合关系(这种耦合是在编译期就确定下来的)。 22 * 23 MovieLister() 24 finder ColonDelimitedMovieFinder( " movies1.txt ); 25 26 } 2.DI的实现方式
1
class
MovieLister
2 { 3 // 其他内容,省略 4 5 public MovieLister(MovieFinderfinder) 6 7 this .finder = finder; 8 } 9 } 接下来我们看看Assembler应该如何构建: private
MutablePicoContainerconfigureContainer()
MutablePicoContainerpico
new
DefaultPicoContainer();
下面就是把ServiceProvider和ServiceUser都放入容器的过程,以后就由容器来提供ServiceUser的已完成依赖注入实例, 其中用到的实例参数和类型参数一般是从配置档中读取的,这里是个简单的写法。 所有的依赖注入方法都会有类似的容器初始化过程,本文在后面的小节中就不再重复这一段代码了。 Parameter[]finderParams { ConstantParameter( " movies1.txt )} ; pico.registerComponentImplementation(MovieFinder. ,ColonMovieFinder. pico.registerComponentImplementation(MovieLister. ); 10 至此,容器里面装入了两个类型,其中没给出构造参数的那一个(MovieLister)将依靠其在构造器中定义的传入参数类型,在容器中 11 进行查找,找到一个类型匹配项即可进行构造初始化。 12 return pico; 13 } 需要在强调一下的是,依赖并未消失,只是延后到了容器被构建的时刻。所以正如图2中您已经看到的,容器本身(更准确的说,是一个容器运行实例的构建过程)对ServiceUser和ServiceProvoder都是存在依赖关系的。所以,在这样的体系结构里,ServiceUser、ServiceProvider和容器都是稳定的,互相之间也没有任何依赖关系;所有的依赖关系、所有的变化都被封装进了容器实例的创建过程里,符合我们对服务应用的理解。而且,在实际开发中我们一般会采用配置文件来辅助容器实例的创建,将这种变化性排斥到编译期之外。 void
testWithPico()
configureContainer(); MovieListerlister (MovieLister)pico.getComponentInstance(MovieLister. Movie[]movies lister.moviesDirectedBy( SergioLeone assertEquals( OnceUponaTimeintheWest 0 ].getTitle()); } 上面最关键的就是对pico.getComponentInstance的调用。Assembler会在这个时候调用MovieLister的构造器,构造器的参数就是当时通过pico.registerComponentImplementation(MovieFinder.class,ColonMovieFinder.class,finderParams)设置进去的实际的ServiceProvider--ColonMovieFinder。下面请看这个容器的参考代码: (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |