转贴:Spring vs. EJB

05-02-03 zjsun
引自:http://www.cnblogs.com/raimundo/archive/2004/09/20/44697.html

我知道我要挨扳砖,没事,来吧:)

赫赫,我来说一下spring vs EJB,首先强调,我不是ejb的拥护者,但我欣赏他的完整、他的学院气,同时也深感他的硬伤,我不是spring的拥护者,虽然去年3、4月间看

到spring的时候曾经让我眼前一亮。对ejb有太多的误解,对spring有太多的吹捧,我希望这是一个相对公平的比较.

我认为spring和ejb的差异在这样三个方面,一个是受众也就是这两个叫framework也好叫platform也好的东西的scope;另一个是component architecture,最后一个是语义

1.Scope比较

先说scope,ejb的scope是什么?ejb针对什么系统来设计的?这个我想一个人一个答案,我说了不算,同样大家说了也不算,我们来看规范(题外说一句,我想本来我没啥

资格在这里谈论ejb,我应用ejb的项目不多,但是我有个习惯,就是读规范学技术,不管别人怎么说先看这个东西是怎么来的,我想这一点还使我有些开口的自信,不至于太

贻笑大方),ejb规范的头几句:

Enterprise JavaBeans is an architecture for component-based computing.Enterprise beans are components of transaction-oriented enterprise

applications.

好了,很明确,ejb是针对transaction-oriented enterprise application的组件,那么也就使说ejb是面向以事务为中心的企业软件,而不是别的。ejb的核心是

transaction,不是domain model或别的。

why transaction?我在电力行业做过一阵信息化软件架构师,在电力这样一个需要处理大量数据的领域里,很少有oo model,而是做完entity分析,交给dba去优化,以数据

性能为主,这样的系统里,数据操作的粒度就是transaction,而不是object或是别的。我想这该算是一个大型企业级系统,我看到的是transaction,因此ejb这个把scope定

在enterprise级的东西而言,这样的设计还使合理。而且ejb对transaction这部分的处理确实比较完整,cmt,bmt,不同的transaction scope控制的都很好。基于这种认识,

我认识transaction script是ejb的标准应用模式,而不是domain model或是别的。

这是对ejb最大的误解的来源,我看过的所有ejb书里,只有o'reilly的一本隐约提到transaction是ejb的中心。其他一律不提,疯狂的鼓吹ejb多好多好ejb多么万能,我想

,如果不知道ejb是transaction-oriented的,那么ejb奇怪的对象模型的确不可接受。

再说spring,spring是什么呢?我没有看到特别明确的定义,不过我想仿照ejb,定义spring为:

Spring is a Javabean-based framework that supporting component architecture development.Spring provides lighter context for heterogeneous entrprise

application.

我e文很差,cet-6 6次都没过,我想说明的是,spring是一个轻量化的组件架构,可以支持多种企业应用程序模式.看到这里有人又该说了,no,no还有ioc,还有aop,没错这

些很cool的特性我没说,但是包含了,component architecture意味着两个方面,component working(编写组件)和container working(编写容器环境),spring的ioc和aop是

用在container working里的.当然肯定还有其他的一些没有概括,但是我想主体我还是说到了的.这样scope就很明确了,spring的基础是javaBean,javaBean支持完整的oo建

模,因此spring可以适用更多的结构,domain model和别的一些。

那么开始比较,spring有一个理论上普适的组件模型,但是鉴于大型应用多为transaction-oriented,那么用spring的理由就是domain model,ejb不能提供完整的oo模型而

spring可以。

结论:由于scope不同,其实比较spring和ejb那个更适合企业开发没什么意义,因为这里面根本就是两个不同的范畴,在scope上指责ejb不如spring,就好像说raimundox,你

就不能替老婆把孩子生了,还让她那么痛苦的怀胎十月。其实我也不想,我也想替,可惜我们这功能.....扯远了,ejb也是,没这功能你怎么强求他呢?你要说ejb设计的不好

,也不对,人家有专门的领域。因此我说,在scope上比较spring和ejb没意义,根本不是一个级别的。

2.component architecture

Component architecture有一个基本观点,就是component和context的分离,理想情况下,component只负责业务的实现,而container提供context,这个context只技术

context,比如事务比如安全的支持。于是,component architecture的基本观点就是business关注点和technique关注点分离,business由component负责,technique由

context或者叫container实现。那么很明确了,component architecture里有两种编程,针对component的和针对container的。

好,有了这个理解,我们可以继续了,如果有人有疑意,那么抱歉,这片文章并不适合您,后面全部的论点都是基于这个观点的,如果不认可这个,下面的也不会认可,您

也不用浪费时间了。

首先看ejb的component方面,ejb在component architecute做得非常的好,ejb就是一个业务组件,在container-managed的情况下,组件通过声明可以应用容器提供的技术

context,当container-managed不满需要的情况下,可以bean-managed,只要保持对外的事务语义就可以了(记得吗?ejb是transaction-oriented,事务最重要)。在ejb里

,组件和容器的约定非常明确,哪些需要组件写,哪些是容器提供的非常明确,这是component architecture里很好的习惯,明确组件和容器的界限(ejb的一个缺点,矫枉过

正,有一些操作也被禁止)。编写代码非常容易,业务,only业务。其实ejb的规范里,ejb的coder其实最好是domain expert,实现业务逻辑就好了。

现在来看spring的component方面,spring以javaBean为基础,贫容器,也就是对容器没要求,于是,spring第一个缺点,contianer和component的约定不清晰(写到这里我

已经听到一些人在叫了,这是spring的优点,自由,别急,后面我会证明这是spring的软肋),但是spring用了一种比较聪明的办法,那就是加强container working.

看一下spring的container working,通过spring的aop api,我们可以很容易的为特定组件定制容器环境,把一个组件需要的容器技术环境以aspect的形式weave到component

里,非常的灵活,也非常的强大,spring通过这种形式来弥补组件/容器约定不足的情况,一切由component选择,容器除了装配(ioc/dip)不提供任何技术context,想要什

么自己来,这个给了component实现者自己选择的权利,很好(但也隐含了spring的最大的不足,别急我后面会说)。

再来看ejb,非常遗憾,ejb container working的能力几乎为0,当然算上jca的话还不算太差,但是那只是资源,而不是技术context。why?因为ejb认为他已经提供了所有

企业级开发所必需的技术context了,事务(ejb里我总把他放在第一位)、分布、并发、安全等等。在ejb看来container working的能力几乎无用,而且不安全,除了jboss开放

了比较多的container working接口其他的ejb container提供这方面的支持很少很少.当然提供很多技术context并不是坏事,要命的是不能配置,要么全用要么不用(倒是很

原子),这是ejb最大的不足,容器环境不可配,也是spring强于ejb的地方。

上面我们已经看到了spring和ejb都是component architecture,那么component能想到的最直接的用处就是复用。那么比较这一点就是比较ejb和spring component

architecture的关键。看到这里spring的支持者们该常出一口气了,spring复用一定强于ejb复用,赫赫,但我的结论正好相反,ejb复用优于spring复用!!收起你们的愤怒

,收起你们不屑,听我把话说完。

在component architecture里,component是业务实现,而不该有技术代码,就算用也要通过容器环境去和容器交互来完成操作,比如ServletContext等东西。那么其实

组建结构下复用的关键不是组建而是容器!!

以前有一个颇有名气的dx(gigix别看了,说你呢),说"COM和EJB都鼓吹模块化和复用,模块化是真的,复用是骗人的",com我不是很熟,不好下结论,ejb呢?ejb不易复用我

承认,但是骗人吗?不骗,后面我给出一种ejb复用的思路大家参考。反正组件一点技术都不作,只有业务逻辑想用就要有相应的容器环境,那么容器环境的复用性才是组件复

用的关键。ejb不易复用是因为如果脱离容器,我们就必须给它提供相应的技术context,事务、分布、并发等等一个也不能少,因此容器外复用ejb效率很低。注意,

是容器外,组件本来就是跑在容器里的,谁让你非要拿出去用),而容器内呢?因为ejb规范规定ejb容器应该兼容,别说webSphere到bea的移植有多难,其实不难,或

者说难度比把spring组件移植到pico复杂一点,当然你用vendor-specified的特性就没办法了,这不再规范内,你违规就别怨人家。因此,ejb的复用是可以的,而且是规范保

证的,容器外也有办法,也不是很难,我后面说。

再看spring,的确他很灵活,但这正是致命伤,component完全是业务实现,但是容器呢?spring怎么保证容器的环境?没有,只能你自己保证,当你沾沾自喜的说,spring

里的component都是pojo,可以很好复用的时候,可曾想到,这复用的代价是要复用容器。比如有个componentA,在SystemA里需要事务模型A和安全模型A,在SystemB里需要事

务模型B和安全模型B,当你从SystemA里复用componentA的时候,你要怎样?重写事务模型B和安全模型B,然后你可以堂而皇之的说,你复用了组件。的确,你复用了组件,但

是你重写了容器,值吗?更可怕的是,spring容器和组件没有约定,那么怎么保证你的组建不写技术代码?ejb只要Bean-Managed并提供统一的事务模型就好了,spring呢?你

靠什么保证?你自己?这是spring一大硬伤,完全container-managed下缺少特定的component边界控制.你可以说,特殊要求的事务模型ejb还实现不了呢,的确,这是有可能

,但是ejb transaction model不能适用的情况有多少?如果真的不行,只能说ejb的简单复用在这里失效。

对于组件还有一个问题就是部署,这也是ejb为人诟病的地方.的确,ejb的部署够复杂,但在ejb规范里有一个专门的角色来负责部署的,ejb是component architecture,那

么比如有一个人来粘合技术和业务,这个人不该是programmer(我刚才说了,ejb的实现者最好是业务专家,实现业务逻辑),ejb的部署才是很厉害的人,他需要知道什么业务

需要什么样的技术支持,该怎样得到性能,因此deployer才是ejb architecture里最牛的,我重来不以为写ejb的是高手,但是一直都敬仰ejb的deployer.当然这里有一个调试

困难的问题,这是ejb的硬伤,没办法,这甚至是组件开发的硬伤.

再来看spring,spring宣称他部署简单,我觉得rod johnson在转移视线,想想看,打成一个war和打成一个ear有多大的区别?那么部署的差异在哪?差异在ejb的deploy

description和spring的context.xml的编写上!在用spring开发中要有一个人来写context.xml这个人往往比较了解系统,知道什么组件用什么拦截,那个组件依赖那个,甚至

会是架构师在作这件事情,那么和ejb里对系统有大局观的人来做deploy有多大区别?可能就是Xml的编写吧,我想在工具的支持下就是熟练度的问题,因此我觉得部署上

spring和ejb差不多,spring不用启server,调试放便些。

结论,在component architecture上,spring灵活,ejb统一完整,各胜擅长,spring的灵活以降低复用为代价,但是如果有common的技术实现,的确很好复用,但是

spring+一套common的技术实现也就约等于ejb了吧?

3.语义

那么spring复用的问题表明了什么呢?其实是缺乏语义的支持,ejb开发可以看作在一个统一的语义环境下来作的,这个语义由ejb规范规定,因此ejb的复用有语义保证,而

spring呢?贫语义,一切都要开发者自己来实现。因此,如果ejb的环境语义可扩展并且可配置(比如去掉分布),那么spring毫无优势,标准的一致的完整的组件架构使ejb

会大有作为,但是现在并没有,才有了spring的火爆.这是一种畸形的胜利,完备语义的输给了贫语义的,问题是什么,强迫消费...谁让ejb非得强迫客户去买用不到的分布式

环境的单?但是统一语义的威力不会因此掩灭,现在有两条路,spring联合os社区,制定lightweight j2ee语义集合,争取成为标准。第二,ejb实现技术语义可配置可扩展。

谁会胜利?不好说,但是似乎ejb的脚步快一些!

附:容器外复用ejb

其实ejb在容器外完全是可以用的,但是为了最大限度保证能用,bean-managed是推荐(不是cmp,bmp而是cmt,bmt),那么怎么传送一个transaction进去?SessionContext(

好像是这名记不清了,都快2:00了,困呀...就是ejb那个context接口),一个接口嘛,自己mock一下,给一个transaction进去就好了。怎么装配?spring的setter

injection。如果用spring,那么cmt也可以实现,拦截啦,不过就看能不能实现ejb transaction model了。entity bean,如果是bmp,就用它好了,cmp,继承一个上

hibernate。这些都模拟好了,找一个in memory的jndi,把spring context封进去,这样相当于我们用spring实现了一个lightweight ejb container(其实就是给spring一个

ejb api的皮),轻到什么程度?除了注射什么都没有。

然后client就可以构造jndi,然后lookup了

看到这里一定有人说,你吃饱了撑的,这么费劲容器外复用ejb,为什么不直接用spring,这样也不够pojo,每个组件都有ejb的类的继承,好,我告诉你这么做的好处,首先

,虽然不够pojo,但是足够bean,因此spring来管理ejb是可以的,证明我的观点容器外使用ejb可以(赫赫,不要说偶rpwt...).其次的,当业务发展了,你的系统需要分布了

,把spring去掉,拿出ejb,redeploy,ok了,延展,稳定,分布都有了,这才是复用该有的境界,改一个部署整个环境换掉,去掉lightweight的ejb container,换乘

heavyweight的就是重量级。

当然这么实现很难,在ejb3里会容易些,我敢打赌,spring以后一定是lightweight ejb container的供应商,免不免费,os不os要看rod johnson了,不过我觉得希望不大。

致谢:

首先感谢dlee,在和他的讨论中形成了这篇文章的主题,然后是冰云,他帮我审稿直到2:04,udoo,perhaps都提出了中肯的意见,谢谢他们.

当然也欢迎大家访问我的blog:www.cnblogs.com/raimundo

zjsun
2005-02-03 21:00
觉得比较有意思,贴出来与大家一起共享和探讨。

myy
2005-02-03 21:58
那么其实组件结构下复用的关键不是组件而是容器!!

--------------------------------------------

我是java菜鸟一个,不过上面的这句话很赞同!

道理很简单,就象Delphi的vcl控件一样,在delphi程序和BCB程序

中复用性是大大的好,但绝对不能直接拿到VC,VB中去用。

banq
2005-02-04 18:57
这是一篇非常有专业水准的、来自实践原创的文章,2004年的Java世界中是一个喧闹、甚至有些偏执的世界。

这篇文章从另外一种角度说出了我心里一直想说的,可惜我一直没有时间,大家可以从我以前文章星星点点中看出与本文的一致意见。

>在scope上比较spring和ejb没意义,根本不是一个级别的

我看到这篇文章的题目 Spring vs EJB, 我立即想,这本不可以比较,又有人来比较,搞些噱头,现在仔细看看,才发现我误解了。

有些人信誓旦旦说:POJO必胜, POJO是什么?普通JavaBeans啊,EJB的名词怎么写?Enterprise JavaBeans, J2EE历史上,先有JavaBeans;后有Enterprise JavaBeans;你现在说POJO必胜,是不是很奇怪、无知的信念?或者说毫无意义的概念,是正确的废话。

哗众取宠的人借用Spring打出Without EJB的口号,非常令我恶心。

>spring第一个缺点,contianer和component的约定不清晰

我以前的帖子说了,使用Spring后,相当于什么都没使用,"Spring宣称它自己侵入性很少,所以,用反义词来说:就是它什么都不做,或者说,它没有什么东西,只有Ioc/AOP模式。"

所以使用Spring的人,你以后就象自己做数据库连接池吃苦去吧,项目失败或被炒鱿鱼被怨恨Java身上。

当然,高手除外,可惜如果我也算高手的话,我宁愿自己做一个框架更顺手,如JdonFramework,这样以后在我架构设计下的业务逻辑都只和我的框架耦合,我复杂跟随技术发展升级我的框架即可,我的业务组件得到了保护和延长了生命,只有傻瓜高手才会基于Spring这样非业界标准将自己的鸡蛋都放在其中,因为老板外行不知,如果来看了Jdon网站,非不把他炒鱿鱼!

>有了spring的火爆.这是一种畸形的胜利

我早就抨击这些虚伪、畸形的热闹,因为这,我竟然被人从"程序员"专题撰稿人的位置上踢出来,可见,要让大家明白争相是多么难的事情。

所幸,技术的真相比社会的真相更容易 更快让人明白,所以我爱技术。

>EJB可以复用

我早说过EJB可以复用,否则就没有SOA赖以生存的基础,JdonSD构件库基本都是EJB组件。

EJB的优点主要是其标准,标准是人定的,因此EJB是有生命的,可以更改的,技术发展了,加入新技术,就这样简单,,,,EJB其它缺点都是技术的缺点,不是EJB缺点,技术是发展的,可以更新的。

那些说EJB这个问题、那个问题的人注意了,这个基本概念都搞不清楚,最好不要搞Java。M$东西很好啊。

qnabOO1
2005-02-05 11:07
俗话说得好啊!

无知者无畏!

写出这篇文章的人已经被EJB 骗的七荤八素滴了!!

我也懒得再花精力跟他一一辩驳了,我只列出一些几百年前就已经被别人讨论过的观点再罗列一下:

EJB所谓的分布式事务支持是建立在JTA规范之上,和EJB本身没有任何关系,只不过它弄了一个恶心的deployment descriptor来做配置。

说spring不支持分布式事务的人更是胡说八道,去好好看看spring的代码,PlatformTransactionManager隔离了JTA Transaction Manager和Local Transaction Manager的不同,让你方便地切换事务管理(Local/Distributed ),而不用去修改代码。

结论就是:

在java里面,分布式企业应用不能without JTA,而恶心的EJB只是挂JTA的羊头来卖狗肉,骗骗那些不懂事的小孩子......

反驳:

开发一个企业级的分布式的应用,当然那了,既然是企业级的,就要兼顾很多问题了,事务,并发,安全,缓存... 当然RMI,和webservice都可以实现,但是却具备不了企业级应用必须的东西,如果单单是为了实现分布式,那我上面列举Hessian, Burlap,XmlRpc......

这些东西都可以实现,但是如何兼顾事务,并发,安全,缓存...这才是我们必须考虑的问题,而EJB恰好解决了这个问题,现在就是如何在非EJB环境下解决这些问题。

辩驳:

如果不考虑业务对象分布的话,EJB容器无非两件事:组件生命周期管理,infrastructure管理。第一件事我们用轻量级IoC容器实现,第二件事我们用AOP实现。这需要在搭建template application时做较多的工作,收益则是有更多的选择,而不是全盘接受所有的infrastructures。对于普通程序员,唯一的变化就是他们编写的组件是POJO,而不是EJB。

辩驳:

那个容器可以设置远程 对象的实例化个数呢???

com+可以 ,ejb容器可以。

spring好像只有“预创建单件模式”吧?

scalable 的软件,不想被无限的client拖垮,必须考虑这个 问题

反驳:

那个容器可以设置远程 对象的实例化个数呢???

com+可以 ,ejb容器可以。

spring好像只有“预创建单件模式”吧?

scalable 的软件,不想被无限的client拖垮,必须考虑这个 问题

辩驳:

先去弄清楚状况,偶们前面讨论的是分布式事务。

不想被无限的client拖垮,只能用集群。

集群和分布式事务是没有关系的。

另外,集群和spring也是没有多大关系的,无论你用什么技术,只要解决各个节点上有状态对象的复制,就能做集群。

It really comes down to where you want to do your load balancing.

You could write a Java-based distributor to do it, maintaining a list of target beans on different servers and their current load, bouncing long-running requests through to each.

Or you could use a load balancer (as Olivier suggested) which does the same thing, but instead of at a Java level it works at the HTTP level. Load balancers can distribute traffic in various configuration patterns based on round-robbin and even based on individual server load. They tend to offer quite sophisticated options as well, such as the target server being able to work at the MAC address level and respond directly to the client rather than directing the response back through the load balancer. Load balancers are a mature technology backed by a lot of R&D and real-world deployments. To give you some idea, see "Three Ways to Load Balance" at http://www.linux-mag.com/2003-11/clusters_01.html.

The nice thing about a dedicated load balancer is you don't have to write it. A Java-based distributor will be time-consuming as you need to poll target beans (to determine their present load/availability) or otherwise track the volume of outstanding requests for each target bean. For all the effort, it will probably be comparatively inefficient unless you spend lots of engineering time. It really isn't the sort of thing you want to be developing if a standard load balancer will meet your needs. Of course many application servers will load balance for you, but then you're adding a layer of software and typically RMI which would probably still not be as efficient as the web services clients being directed by a proper load balancer at a nice low OSI layer to an available web container.

oliverhutchison:

引用:

Another option would be to look at writing your "job" processing system using a message driven approach. ActiveMQ has recently added support for message driven POJOs which could be exactly what you're after. See: http://sourceforge.net/mailarchive/message.php?msg_id=9896311. A great thing about JMS is that if you don’t need a distributed system you can run the message producers/consumers all "in process" with very little overhead but if/when you do need to add servers you are insulated from a lot of the mechanics of this process.

You're spoilt for choice on this one, but don't forget, (as Ben often says;)) KISS (keep it simple stupid), before you start creating a super distributed architecture with all the bells and whistles it's worth spending a bit of time to analyze whether this is really something you need.

Ollie

banq
2005-02-05 20:39
>对于普通程序员,唯一的变化就是他们编写的组件是POJO,而不是EJB。

关键前提在这里:

是面向组件POJO编程方便 还是面向容器EJB编程方便。

我想这个问题探讨下去也是傻瓜相机和手动专业相机好之类的问题。

这两类人估计谁也无法说服谁,我自己也在适当时候选择适当技术:我在做项目应用时,用EJB; 在开发特殊产品,如框架、J2me+J2EE等基于实时分布式系统时则会使用到Aop/Ioc之类。

我不建议在普通应用中直接接触到Aop/Ioc之类的POJO,例如在一个Spring应用中,如JPetstore的Spring XML配置中,我们不仅仅看到业务组件component,也看到一些基础组件:对象池和JTA等。

Spring即使现在功能不强大,将来也可能变得强大,问题在于,是否有必要将这些基础设施暴露出来,就象一个房子的布线等,是不应该暴露在外面的。

因为不是每个人是电工、不是每个人是拦截器爱好者、不是每个人是优雅的偏执狂啊。

我设计的JdonFramework的配置文件只有Model和Service配置,这两种是完全面向应用的;而那些电线、拦截器可以通过代码根据自己爱好干预,后者在EJB中无法实现,也是EJB遭受指责的地方。

但是Spring又把这两者混淆在一个配置文件里,走向另外一个极端。

我不是自夸JdonFramework如何优秀,在很多方面有问题,但是在这点上,它是一个探索。

zbw
2005-02-06 09:39
banq,我的帖子哪里犯规了???

为什么要删除?

qnabOO1
2005-02-06 10:35
>>>>>

是面向组件POJO编程方便 还是面向容器EJB编程方便。

我想这个问题探讨下去也是傻瓜相机和手动专业相机好之类的问题。

这两类人估计谁也无法说服谁,我自己也在适当时候选择适当技术:我在做项目应用时,用EJB; 在开发特殊产品,如框架、J2me+J2EE等基于实时分布式系统时则会使用到Aop/Ioc之类。

我不建议在普通应用中直接接触到Aop/Ioc之类的POJO,例如在一个Spring应用中,如JPetstore的Spring XML配置中,我们不仅仅看到业务组件component,也看到一些基础组件:对象池和JTA等。

Spring即使现在功能不强大,将来也可能变得强大,问题在于,是否有必要将这些基础设施暴露出来,就象一个房子的布线等,是不应该暴露在外面的。

<<<<

首先声明一点,普通的POJO并不意味着要写比EJB更多的代码,POJO的核心概念是“don't call me, I will call you",从这点来说,如果把POJO脱离一个管理他们的容器来讨论是显得毫无意义的。 POJO的特点是通过轻量级容器解耦了组件间具体类之间的依赖,使得接口依赖成为可能,而IOC/AOP越来越完善的规范,使得我们切换基于POJO的应用在不同的容器成为可能,如果要给这些容器置上一个大致的前提规范:至少应该提供IOC实现,至少应该提供声明性配置,至少应该提供事务管理。

当然,你可以更具体的提出自己的需求,比如:rod.johnson进一步阐述了底层框架所应该达成的目标,如果你希望能够提高你开发企业应用的生产率,那么你应该考察你所采用的底层框架是否符合rod.johnson《java expert one-on-one ...》里面所提到的一些基本原则。

看到banq说出”POJO“是傻瓜相机这个比喻,我可以断定banq没有很好的理解POJO的概念,至少没有理解POJO的协作意义。

POJO并不意味着它要管理一个企业开发中所有的事情:比如 怎么获取它所依赖的组件,怎么管理事务? 怎么优化性能? 。。。。。

相反,它的精髓是反而不需要关心这些事情,而是仅仅要关心它本身所要实现的逻辑。

怎么获取依赖组件,IOC可以很好的解决。

怎么管理事务,类似Spring的框架提供了可声明性的事务配置(当然还有一种编程时的配置)

怎么优化性能。AOP可以很好的解决这个问题。

所以,编写一个POJO,你所需要真正关心的是你所要实现的业务逻辑,而其他所依赖的组件,你只要暴露一个setter方法即可,在具体的编码中,你可以完完全全的针对你所依赖的组件的接口进行编写代码。

看到gigix里面的那篇比较时兴的文章,看到其中引用的一段代码:

public JdbcDAO() {

      ServiceLocator sl = new ServiceLocator();

      dataSource = (DataSource)    sl.getDataSource(JNDINames.DATASOURCE);
<p>

这种代码是很bad smell的。限定死了人家定义DataSource的name,并且依赖于具体的ServiceLocator实现。 ServiceLocator不应该出现在任何一个由 容器管理的POJO中。

如果JdbcDAO不是通过容器管理,那么就请立即修改,让它由容器管理。不然容器就显得毫无意义了。

结论:datasource应该通过IOC注入,而不是直接用servicelocator来寻获。

至于你说的不应该暴露基础设施的建议,我也是很反对的。作为一个以技术为生的人,不应该抱着MS VS开发式的思维,全自动化往往意味着我们在转向“体力 蓝领”,也往往意味着我们越来越有被蒙骗,垄断的危险。同样,仅仅因为开发平台提供了似乎无可挑剔的底层infrastructure 就无视这些基础设施:比如事务管理,对象池管理等等。 这样的后果是显而易见的,就是造成你所开大应用严重依赖于特定的平台/容器,并且因为透明,所以导致了bug 也透明起来。当然,你要保证你选择的容器足够好,虽然很多“愚蠢”的人坚信“价钱越高,得到的平台越好越标准” 。

spring暴露这些基础设施,正是给开发者更为广泛的选择,比如JDBC 的事务足以应付大多数企业开发的事务管理,而JTA 事务虽然是标准,但在非分布式应用中,它反而显得繁琐。 至于缓冲池管理,这是任何一个企业开发都必须重视的咚咚。没有理由无视它的存在。

虽然“偷懒”是一个优秀开发者的座右铭,但是这里的偷懒的意义不在于 不管,而是先弄清楚了,管透了,再好好的在具体的编码/开发中偷懒。

banq
2005-02-07 09:43
你写这篇文章时,要么很激动,没有仔细思考,要么你可能也没有了解POJO的概念。

你说我将”POJO“是傻瓜相机这个比喻,我没有这么比喻啊,只是我将顺序倒了过来,前面说POJO和EJB;后面说傻瓜相机和手工专业相机;如果对这些概念不深入理解的话,按照字面推理就推理出你的结论:POJO是傻瓜相机;

当然这不是我故意设置的陷阱。

POJO是专业手工相机,什么事情都要开发者做,所以才有了后来的Enterprise JavaBean :EJB。 EJB类似傻瓜相机。

我想这可能是你的小疏忽。

我一再强调:应用者不都是各个领域的专家,你害怕被垄断,但是你不能什么东西都透明,如皇帝新装啊,衣服还是要的,但是衣服是可以脱的,你要透明,就脱衣服啊,不是很好吗?干吗光身来回呢?

所以,我们不需要Spring那样的全身透明;也不能被M$这样东东蒙蔽和垄断。

关于jdonFramework,你切忌道听途说,关于jdbcDAO这个问题,我想你误解了,没有考虑到这是在EJB下使用:

>>限定死了人家定义DataSource的name

>>结论:datasource应该通过IOC注入,而不是直接用servicelocator来寻获

JdbcDAO是遵循J2EE设计模式的DAO模式,参考Petstored的Category DAO模式,DAO调用方式是: EJB(SKSB) + DAO + JDBC/Hibernate

所以jdbcDAO是被EJB调用的,注意jdbcDAO这段代码中的servicelocator是从哪里导入的,如果我没有记错,应该是 xxx.xxx.xx.ejb.servicelocator。

也就是说,Datasource的Name是EJB的reference name,而reference name是指向数据源的JNDI,JNDI再指向具体数据库。

J2EE就是通过这样的松耦合来实现了解耦。

所以,我还是奉劝有些人,多学点东西,特别是将J2EE规范标准下载下来读读,有不懂在这里来问就好,不耻下问。

不要以挑战的姿态来说话,你说我会教你吗?

qnabOO1
2005-02-07 11:27
>>>>

JdbcDAO是遵循J2EE设计模式的DAO模式,参考Petstored的Category DAO模式,DAO调用方式是: EJB(SKSB) + DAO + JDBC/Hibernate

所以jdbcDAO是被EJB调用的,注意jdbcDAO这段代码中的servicelocator是从哪里导入的,如果我没有记错,应该是 xxx.xxx.xx.ejb.servicelocator。

也就是说,Datasource的Name是EJB的reference name,而reference name是指向数据源的JNDI,JNDI再指向具体数据库。

J2EE就是通过这样的松耦合来实现了解耦。

<<<<

前面关于相机的那段比喻,我确实存在误解。

至于你说得

JdbcDAO是遵循J2EE设计模式的DAO模式,参考Petstored的Category DAO模式,DAO调用方式是: EJB(SKSB) + DAO + JDBC/Hibernate

所以jdbcDAO是被EJB调用的,注意jdbcDAO这段代码中的servicelocator是从哪里导入的,如果我没有记错,应该是 xxx.xxx.xx.ejb.servicelocator。

也就是说,Datasource的Name是EJB的reference name,而reference name是指向数据源的JNDI,JNDI再指向具体数据库。
J2EE就是通过这样的松耦合来实现了解耦。
<p>

我还是存有异议,既然你使用了PicoContainer,为何不将解耦进行到底呢?

既然你的JDon 框架很大一部分为了EJB而建立,为何不将PicoContainer作为彻底将你的业务逻辑层 和 EJB/别的J2EE容器解耦的中间层呢? 这样的话,无论对于测试还是部署都有巨大的好处。

针对你说的JDBC DAO,因为在你的源代码中,我找不到你的这些类,我只能就着我的思维发表一点拙见:

可以参考Spring,用一个JndiObjectFactoryBean专门处理JNDI类的引用,下面给出一个转贴以示说明:

<!-- 通过jndi的方式来调用datasource,即使不一定是在j2ee环境中也可以正常使用

默认情况下,如果没有指定,"java:comp/env/"将放在后面jndi名称前面 -->

<bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName"><value>jdbc/myDatasource</value></property>
<!-- 如果你不想使用 'java:comp/env/'前缀的话请设置下面的值为true, 默认值为false -->
<property name="resourceRef"><value>true</value></property>

<property name="jndiEnvironment">
<props>
<!-- The value of Context.PROVIDER_URL -->
<prop key="java.naming.provider.url">t3://localhost:7001</prop>
<prop key="java.naming.factory.initial">weblogic.jndi.WLInitialContextFactory</prop>


</props>
</property>
</bean> 

<p>

而你 的 jdbcDAO可以这样写:

public JdbcDAO() {

}

public void setDataSource(DataSource ds){

dataSource=ds;

}

public DataSource getDataSource(){

return dataSource;

}

...

}

你的JDon 配置文件中可以类似这样定义:

<jdbcDAO>

<dataSource ref="dataSource" />

....

</jdbcDAO>

如果datasource是自定义的,则只需要这样配置:

<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
		<property name="driverClassName"><value>org.hsqldb.jdbcDriver</value></property>
		<property name="url"><value>jdbc:hsqldb:data/jert_web_test</value></property>
		<property name="username"><value>sa</value></property>
		<property name="password"><value></value></property>
	</bean>

<p>

既然你的设计使用了IOC的概念,并且采用了PicoContainer为微核心,那么有什么理由不使用IOC呢?

qnabOO1
2005-02-07 11:38
其中设置的:

<property name="jndiEnvironment">

<props>

<!-- The value of Context.PROVIDER_URL -->

<prop key="java.naming.provider.url">t3://localhost:7001</prop>

<prop key="java.naming.factory.initial">weblogic.jndi.WLInitialContextFactory</prop>

</props>

</property>

实际上就是设置Context初始化的时候设置的Properties属性。

具体请参考:

这个连接:http://faq.lenovo.com/layout/kb/entry.jspa?entryID=12&categoryID=29

至于具体的实现,可以参考Spring的源码。

banq
2005-02-07 11:48
>JDon 框架很大一部分为了EJB而建立,为何不将PicoContainer作为彻底将你的业务逻辑层 和 EJB/别的J2EE容器解耦的中间层

>使用了IOC的概念,并且采用了PicoContainer为微核心,那么有什么理由不>使用IOC呢?

这个问题回答没有那么简单,涉及很多因素,其中有一点是又回到了我们之前讨论的问题上了,我不想将所有的电线象Spring那样暴露在一个配置文件里;或者说暴露给所有应用者。你举例的Spring调用Datasource的方式就象暴露在房间里电线排线一样。

EJB这方面比较巧妙,所以我倾向EJB,当然我没有必要做EJB已经做过的。只要导引用户去用EJB。

JdonFrameowrk既支持EJB,也支持POJO,这个方向你可以使用PicoContainer等极端地装载你所有的业务逻辑层,缺点是:需要象Spring那样进入手工排线阶段。这方面Spring比较擅长,jdonframework可能也不会做,也回只做一个引导。

banq
2005-02-07 12:09
补充:jdonFramework不一定引导到Spring,这些想法还没成熟,正在设计中,最重要的是,将业务逻辑用jdonframework包裹,然后运行在其它容器中,保护已有组件。

试图在探索方向还有: MDA,以及提供POJO自由迁徙到EJB容器等。

qnabOO1
2005-02-07 12:40
我个人认为banq 你有一个根本的原则搞混淆了。

“暴露” 和 “可扩展” ,你似乎在两者之间互相矛盾。

一个咚咚可扩展,那么他必须要暴露它所需要的扩展点。

当然,为了简化开发, 默认的Default实现都会随之提供。 这点并没有增大开发人员的开发量。

就像上面的datasource,暴露DataSource是使得开发人员根据具体项目可扩展的关键。

jdbcDAO对于DataSource的获取,暴露给开发人员自己扩展实现,又何偿不可呢 ? 正是因为这样,开发人员可以轻松扩展为从JNDI中获取,或者自己定义。

假设,你的jdbcDAO需要一个用户自己定义的DataSource,那么你必须又得写出另外一个JDBC DAO,此时,你不会跟我拿出J2EE规范跟我说:用户必须在JNDI中定义它的DataSource吧!

另外,看了一下你的cache包,忍不住说两句:

这是典型的重复造车的行为。

现在已经有优秀的多个cache 产品,何必自己实现一个:UtilCache ?

给你一个类似的实现:

cache接口同你一般。

另外参考一些优秀的项目,给你提供一个CacheProvider:

import java.util.Properties;

public interface CacheProvider {

public Cache buildCache(String regionName, Properties properties) throws CacheException;

public long nextTimestamp();

}

对于Cache的实现, 你可以用OSCache 或者JCSCache来实现。

针对每一个不同实现的Cache,分别提供一个CahceProvider以封装生成具体Cache的逻辑。

这样,就使得用户可在配置文件中选择他所需喜欢的Cache:比如OSCache或者JCSCache等等。 用户需要改的仅仅是它所需要的CacheProvider .

banq
2005-02-07 12:46
关于jdonframework到其它帖子讨论,我和你讨论到此为止,我不想说一些伤害你自尊的话,你拿一个个问题来问我,我都可以回答你,可惜这样问题回答太简单,我都开始怀疑你是那个gigix,因为你们的思维和知识水平是类似。

对不起,不要再接我的话题,如果有伤害你,道歉。讨论别的问题的,关于JdonFramework有关于请教的到项目工程论坛吧。

猜你喜欢
3Go 1 2 3 下一页