精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2005-12-06
ajoo 写道 ioc容器的出现并不也从来不应该影响业务代码的设计。
如果你发现有些工厂因为有了ioc容器可以不用了,一般就是两个原因: 1。 这个工厂没有ioc容器的时候本来也不应该用,你只不过偷懒了,或者根本没有意识到这个错误。 2。根本就应该用工厂。你试图利用ioc容器来代替工厂的做法是错误的。 谢谢! ajoo 写道 至于说用了ioc容器就和容器紧耦合了。也是两个原因: 1。这个容器产品不够好。侵入性太强。比如avalon,比如spring里面一些XXXAware的接口。 2。你用错了。依赖注入容器被你当作廉价的service locator了。拿菜刀去削铅笔你说是谁的错? ajoo兄是指我说的“而且使用Ico和AOP后,我们就必须要和某些API建立了“紧耦合”么? 我的意思是,作为开发人员要学习使用某个container的API, 如果以后换container的话,还要学习新的API。而Dsign patterns和任何API和编程语言都是无关的。 |
|
返回顶楼 | |
发表时间:2005-12-07
开发人员要学习容器的api做甚?容器的api是给你扩展容器用的(假设你用的是一个xml或者脚本外壳,而不是直接操作容器),大家平时没事都扩展容器来玩么?
|
|
返回顶楼 | |
发表时间:2005-12-07
ajoo 写道 开发人员要学习容器的api做甚?容器的api是给你扩展容器用的(假设你用的是一个xml或者脚本外壳,而不是直接操作容器),大家平时没事都扩展容器来玩么?
第一次听到这种论调,请问你不用容器的API如何使用容器? 下面的例子我直接从martin fowler的Ioc文章里面copy过来的: picoContainer: private MutablePicoContainer configureContainer(); { MutablePicoContainer pico = new DefaultPicoContainer();; Parameter[] finderParams = {new ConstantParameter("movies1.txt");}; pico.registerComponentImplementation(MovieFinder.class, ColonMovieFinder.class, finderParams);; pico.registerComponentImplementation(MovieLister.class);; return pico; } Spring: public void testWithSpring(); throws Exception { ApplicationContext ctx = new FileSystemXmlApplicationContext("spring.xml");; MovieLister lister = (MovieLister); ctx.getBean("MovieLister");; Movie[] movies = lister.moviesDirectedBy("Sergio Leone");; assertEquals("Once Upon a Time in the West", movies[0].getTitle(););; } 有没有用到API, 不言而喻了吧! |
|
返回顶楼 | |
发表时间:2005-12-07
可能你没有理解ajoo的意思,他说容器的api应该是指关于容器内部infrastructure实现的,容器提供出的public api是可供客户端调用的,他所谓的扩展应该是指客户端通过继承或者使用包装,或者用兄弟你掌握的dp来纳入你的应用中,这称为客制化,但大多数时候,我相信spring的facade api已足够好,没有什么理由再去客制了
|
|
返回顶楼 | |
发表时间:2005-12-07
ajoo 写道 ioc容器的出现并不也从来不应该影响业务代码的设计。
至于说用了ioc容器就和容器紧耦合了。也是两个原因: 1。这个容器产品不够好。侵入性太强。比如avalon,比如spring里面一些XXXAware的接口。 2。你用错了。依赖注入容器被你当作廉价的service locator了。拿菜刀去削铅笔你说是谁的错? 关于第一点,我有些补充,使用某一特定容器,必然会产生对该容器环境的一些依赖,好的容器实现应该是说能够体现出以最少的成本,来消除这种依赖的能力 ,如果你真的需要完全脱离容器,可以用上发贴这位兄弟所倡导的dp之adapter来使用容器api,dp的adapter是个很有用的pattern,有时候可以用来处理许多杂碎的活儿 关于第二点,我有些疑问,ioc容器不能用作service locator吗,service locator引自j2ee core pattern,是在ejb身上被广泛采用的pattern,如果采用重量级容器,势必由service locator这个单访问点,籍由jndi创建或者cache出context来得到某个重量级对象的引用,而使用spring这样的轻量级容器,原则倡导without ejb,那么service locator应该也同样有理由可以lightweight吧,spring的appcontext应该可以看作是个廉价的service locator,我是说如果你需要把它看作是个locator的时候,也就是说把bean id看作是jndi,当然你也可以自己去实现一个singelton locator来使用spring的这个appcontext,你的意思是不是指不经加工,裸露使用这个context吗,是的,的确这样不好,还是有其他你认为不好的把ioc容器用作service locator的坏的例子吗 |
|
返回顶楼 | |
发表时间:2005-12-08
polygoncell 写道 ajoo 写道 开发人员要学习容器的api做甚?容器的api是给你扩展容器用的(假设你用的是一个xml或者脚本外壳,而不是直接操作容器),大家平时没事都扩展容器来玩么?
第一次听到这种论调,请问你不用容器的API如何使用容器? 这种common sense不用我来说了吧。 当然在最顶层,bootstrap的时候,比如说那个main()函数里面,需要调用一下spring/pico/whatever的api来拿到你的那个或者那几个最顶层的对象。这还用说? 我是说除了bootstrap,任何其它的代码,比如业务代码里面就不要依赖容器。而bootstrap的代码就那么几行,集中在一个地方,耦合不耦合的有什么大不了的问题? class Bootstrap{ public void bootstrap();{ Application app = (Application);container.getInstance("app");; app.start();; } } |
|
返回顶楼 | |
发表时间:2005-12-08
引用 关于第二点,我有些疑问,ioc容器不能用作service locator吗,service locator引自j2ee core pattern,是在ejb身上被广泛采用的pattern,如果采用重量级容器,势必由service locator这个单访问点,籍由jndi创建或者cache出context来得到某个重量级对象的引用,而使用spring这样的轻量级容器,原则倡导without ejb,那么service locator应该也同样有理由可以lightweight吧,spring的appcontext应该可以看作是个廉价的service locator,我是说如果你需要把它看作是个locator的时候,也就是说把bean id看作是jndi,当然你也可以自己去实现一个singelton locator来使用spring的这个appcontext,你的意思是不是指不经加工,裸露使用这个context吗,是的,的确这样不好,还是有其他你认为不好的把ioc容器用作service locator的坏的例子吗
ioc容器当然可以拿来当作service locator。只不过买椟还珠罢了。理想的情况就是用容器组装对象。从容器中把对象拿出来后(拿的时候当然还是service locator,就象你不管怎么抽象,怎么工厂,怎么ioc,最终总要有个地方具体地new一样),就跟容器说byebye了。所有的依赖关系都已经处理干净了,所有你需要的service都已经注射给你了,你还locate个啥呀? |
|
返回顶楼 | |
发表时间:2005-12-08
ajoo 写道 这种common sense不用我来说了吧。
当然在最顶层,bootstrap的时候,比如说那个main()函数里面,需要调用一下spring/pico/whatever的api来拿到你的那个或者那几个最顶层的对象。这还用说? 我是说除了bootstrap,任何其它的代码,比如业务代码里面就不要依赖容器。而bootstrap的代码就那么几行,集中在一个地方,耦合不耦合的有什么大不了的问题? class Bootstrap{ public void bootstrap();{ Application app = (Application);container.getInstance("app");; app.start();; } } 1。 老兄在整个系统中integrated某个Ioc container,却只用来获得几个最顶层的对象,是不是有点舍近求远了,为了用Ioc container而用Ico container? 如果只是为了获得区区几个对象, 直接生成不就行了,何必绕这么大一个圈? 2。假设我们获得了最顶端的几个对象,那么请问你如何获得其他对象?全部通过这几个最顶端的对象来获得?不太现实了吧!通过容器而又不是用容器的API来获得对象?可能实现么? 3。Ioc的最大好处是使得POJO们之间解耦合, 如果POJOs和容器产生了耦合,那绝对是用错了。 我说的耦合是系统和某个Ico container产生耦合(通过API)。 从你的例子来看,对象应该通过xml配置文件来实现,而系统是通过某个container的API来解读xml进而生成相应的对象的,即使开发人员没有在编码中呼叫这些API(这个是不可能避免的),我们也不能说系统和这个container是解耦合的,因为系统用到了这些API。如果不用xml, 那就得用代码呼叫API注入对象,更是耦合。 p.s. 本来我是不想谈Ioc的,可是没有办法,大家眼里只有Ioc。大家真的没有必要把Ioc抬得这么高,她也不过就是个pattern, 不比其他pattern高多少。眼光放的开阔些。 |
|
返回顶楼 | |
发表时间:2005-12-08
spiritj 写道 可能你没有理解ajoo的意思,他说容器的api应该是指关于容器内部infrastructure实现的,容器提供出的public api是可供客户端调用的,他所谓的扩展应该是指客户端通过继承或者使用包装,或者用兄弟你掌握的dp来纳入你的应用中,这称为客制化,但大多数时候,我相信spring的facade api已足够好,没有什么理由再去客制了
准确些,应该是ajoo没有理解我的意思,我说的是"某些API", facade API难道不是容器的某些API么?在朝这个方向讨论下去可就成了讨论汉语语义了 |
|
返回顶楼 | |
发表时间:2005-12-08
引用 2。假设我们获得了最顶端的几个对象,那么请问你如何获得其他对象?全部通过这几个最顶端的对象来获得?不太现实了吧!通过容器而又不是用容器的API来获得对象?可能实现么?
现实,太现实了。ioc容器就是这么用的。 “获得其它的对象”?你还不懂什么叫ioc(更精确地说:dependency injection)吧?这外行话也说得出来? 所谓依赖注入就是根本不主动获得其它对象。你需要什么都已经注射给你了,还苦哈哈地“获得”个什么劲? “直接new”?说的轻巧。还是不懂ioc的问题。你当就"new App()"这么简单?App的dependency你要注入吧?它的dependency的dependency要注射吧?这些从属对象的生命期要管理吧?这么一整张复杂的对象网络你就new一下就都出来了?知道什么叫"wiring"么?容器不过就是负责管理对象的依赖并把整个对象网络构造起来而已。说难不难,但是也不象你想的那么简单。 不懂就谦虚点吧,同学。 |
|
返回顶楼 | |