也欢迎讨论有关Ioc模式的框架产品 picocontainer (http://www.picocontainer.org). Spring 或其它相关产品。

我是从楼主的例子里转到这个页面的,我发现楼主的例子对Pico的观点阐述的不是很好,Pico是Type3的IoC Container,也就是Constructor injection的Container,而banq的例子是典型的type 1也就是一种侵入式的interface式的依赖声明(Alvaon就是这样),而不是pico推荐的非侵入式的构造子式的依赖声明,当然这两种方法没有优劣,但是作为pico的IoC例子,我不得不说banq给出的是一个很不恰当的例子。

昨天专门把这个文章打印拿回家看,可看以半天也没看懂(或许悟性不够),板桥能不能讲得再详细些:)

to raimundo
多谢建议,其实我有两个Picocontainer例子,前面一个简单的,与工厂模式比较的是典型的Type3;后者也展现了picocontainer的另外一种用法,其实后者我认为还是构造器注射,也可以参见picocontainer主页的关于水果的举例。我举这个例子主要是为了说明向AOP方向靠拢。

这篇文章不是初级概念读物,因此,一般初学者比较难懂,这篇文章其实是一篇探讨类的文章,我试图通过这篇文章找出依赖注射的优点,以及如何正确使用。

有人以为依赖注射模式打开了框架产品大门,其实,在这概念出现之间,框架产品基本都已经做了,在我设计JdonSD框架时早就使用了这样的注射机制。

但是使用依赖注射开发框架时必须注意它的特点,否则很难把握使用,通过这篇文章我总结了这些特点:首先它只是转移了依赖,而不是消除,而且依赖注射被移植到客户端,这就有一个限制:具体子类必须和注射事件激活在同一个地方,也就是说:药水和注射动作必须结合在一起。注射动作的能量来自两个来源:一个系统自身启动的能量,通过java application的main()实现,在main方法中,可以将具体子类(药水)注射到picocontainer中;

还有一个是系统运行时,由系统用户通过界面键盘输入和鼠标激活的能量,这种能量一般是传递到MVC模式的action中,你可以在action中将具体子类(药水)注射到picocontainer,但是你会发现,这样使用的价值不大,几乎为零,不如使用工厂模式;或者Ioc第一类型,其实EJB的JNDI就是在这种场合下使用的,所以,EJB JNDI虽然烦琐一点,但是从picocontainer和Spring等提供的IOC新实现方式来看,他们还是无法代替JNDI的作用,因此由此提出J3EE(不是J2EE)真是有些唐突啊。

我的这篇文章,就是试图得出picocontainer或Spring之类的局限性,因为任何一个事物都有自己的应用范围,没有全能的技术和思想,找出新事物的局限性,你也许就能把握它了。


to raimundo
更正,这个例子确实属于接口注射(入侵)实例,我上篇有误。

不过,这篇文章确实不是为了说明Picocontainer,而是着重从过去和未来的高度认识Ioc模式,因为Picocontainer很简单,只是使用Picocontainer作为举例,当然最好使用Alvaon举例,可惜它太复杂,我也不喜欢它。

个人感觉 IOC和依赖接口设计并不对立
只不过是依赖接口设计在系统级角度的应用而已


另外,也许是先入为主原因,看banq的这篇文章有点怪怪的
有些翻译没有采用国内最贴切的翻译(可能是怕涉嫌抄袭的原因,呵呵),个人感觉pawa的IOC文章也很不错

to iamwls
翻译的词语我都是自己采取我认为贴切的词语,按照我的理解翻译的,如果看了别人的文章,再看觉得怪,呵呵,我看别人文章也觉得怪,觉得没有翻译到点子上,比如InJecting我觉得翻译“注射 ”很贴切。还有Aspect我认为“切面”很合适,“方面”多怪啊。component翻译成“组件”好啊,翻译成“构件”真是怪,组件是一组组的东西,这很符合component的英文单词,构件含义太大了,component一般是基本单位,象工厂的小组意思,构件已经有架构的意思,component我看还没到那份,component只是构成架构的最小部分,Service或framework倒是可以称为构件的。


IOC这个东西如果不结合AOP,价值会少很多。
在spring中,对于web应用,框架的使用者通过定义appContext.xml(名字不重要)来配置组件及其关系,用你的话说,就是药水是由组件配置者提供,但是注射动作却是框架实现的,这个对于非分布式应用而言,要强于jndi。 type2/3 + AOP的方案,其组件的内聚性和灵活性,以及框架的灵活/适应性,都要远胜过type1的方案。从"关注分离"的角度来说,type2/3才是更进一步的实现。另外,基于spring的分布式解决方案,其分布方式不是由spring实现的,从这个意义上来说,虽然spring旨在作为ejb的一种轻量级替代,但是和真正需要cmp的应用,是合作而不是竞争的关系。
没有一种框架能够用以"消除"组件间的依赖性,组件依赖只是业务依赖的一种映射,关键在于这种依赖的表示方式。至少,大家都不喜欢硬编码(有多种形式)的依赖方式。
btw,依赖注射只是IOC的某一部分的一个重命名,除了这个名字,其概念已经出现很多年了。

IoC为什么一定要结合AOP?AOP对非IoC和IoC有什么不同的影响呢?

其实JNDI只是一个访问接口,就像JDBC,和IoC不是对等的,IoC中也可以使用JNDI自动获取分布式的依赖组件,比如通过配置文件声明.

BTW,哪些应用是真正需要CMP的?

hehe,少安毋躁。
这里和jndi相比的并不是ioc或者框架本身,而是框架的"组件依赖"表示机制,或者说spring的那种将依赖表述于配置文件的方式。
IOC框架不结合AOP的话,实现某些功能,如安全性,事务管理,或多或少都要用一些"侵入"式的方案,对组件有不必要的限制。从原则上来说,组件只应当与业务逻辑相对应,而独立于这类基础技术问题。这应该也是type1相对于type2/3的最大区别,type2/3提供了一种非侵入式实现的可能。
至于真正需要cmp的应用,banq比我更清楚。我从来不认为jdo或hibernate的方式能够在分布式应用上替代cmp。

>>首先它只是转移了依赖,而不是消除,
>>就是药水是由组件配置者提供,但是注射动作却是框架实现的,
>>>>type2/3 + AOP的方案,其组件的内聚性和灵活性,以及框架的灵活/适应性,都要远胜过type1的方案。从"关注分离"的角度来说,type2/3才是更进一步的实现。
非常同意上面的说法。尤其是--type2/3 + AOP的方案,其组件的内聚性和灵活性,以及框架的灵活/适应性,都要远胜过type1的方案--现在有些体会,但真是心有余而力不足,不能象斑竹那样给出这样一篇文章。

记得学习OO时有这样一个说法:是外界的一个触发,导致消息在一个对象网(web of objects)的运作。就象我们现实生活中人类的合作。这也就是斑竹所说的“启动能量”的问题。那么这种关系比我们用类图画出的静态的持久性关系比较更能反映系统的功能性,这是依赖性关系。

项目的成功有时更依赖于业务人员或开发人员对业务的了解。那么这些业务如何更好的让计算机程序接受呢?本人愚见,如果用JNDI的方式,即TYPE I,那么是程序人员自己定义和处理了业务的操作;而如果是TYPE II && III,就可以把一些工作更好的交给关注业务的人员。

现在的spring采用留有setXXX的方式进行类及类间倚赖注册,其实就是AOP中的advice。那这种advice可以说是有框架动态关注的,通过的方式更多的采用Intercepter,这些Intercepter(join point)就构成了横切。那么灵活性和可扩展性就相应增加很多。

同样,象spring一样,无论业务还是这种临时的依赖都可以通过XML文件来进行配置,进一步,可以通过界面,图形,程序自动化方式(xdoclet,cglib)等方式来生成,那么程序可控性,效率会进一步提高。

public class client{
   public static void main( String[] args ) {
    DefaultPicoContainer container = new DefaultPicoContainer();
    container.registerComponentImplementation(CImp.class);
    container.registerComponentImplementation(B.class);
    B b = (B) container.getComponentInstance(B.class);
    b.someMethod();
   }
}


Banq,这个B b的构造变量应该是CImp.class吧。

banq, 正要请教关于pico的问题。

从你的例子,我看不到需要使用一个额外的库的需要啊。

我以前一直都是让构造函数初始化一些接口变量,没想别的,就象你另一个帖子说的,能拖延的,就拖延,不想过早做决定而已。
只是不知道这东西也给起了一个好听的名字"ioc"。

但是,我在最终拖无可拖,必须做assemble的时候,都是直接调用实现类的工厂或者构造函数,不曾觉得需要一个container来做什么注册class之类的动作。

那么,为什么不


new PicoUserManager(...)

而非要

container.register(PicoUserManager.class);

呢?
后者不仅需要一个额外的container机制,还要依赖低级的reflection,构造函数也无法隐藏。
这样作的好处在哪里?

换句话说,我的疑问比较低级:Pico到底能为我做什么?我为什么想用pico?
ejb container能帮我做分布式,persistence,事务。这个pico能做什么呢?

to ajoo
>Pico到底能为我做什么?我为什么想用pico?
我在文章中,将Pico和工厂模式比较,两者的各有特点,两者可以说都类似工具,在你需要解决特定问题时,才会派用处。

抽象地说,pico类似动态代理,可以实现AOP,Naning项目采取的是pico,还有你想做容器之类的软件也可以,例如portlet container就可以用pico,Exo项目就是这么用的,挺不错。