一、业务代理模式(buiness proxy)
在j2ee系统中,一般划分为表现层和业务逻辑层,为实现表现层和业务逻辑层之间的最大限度解耦,引入业务代理模式,这样,当表现层或业务逻辑层具体实现技术发生时,对彼此的影响很小,当然,如果希望实现完全解耦,我们可以使用消息系统jms来实现,本文章只讨论同步系统范畴。
二、工厂模式
以一个struts+hibernate为例,以下代码是struts的action实现方法代码:
public actionforward update(actionmapping mapping,actionform form,httpservletrequest request,httpservletresponse response)throws exception { egform egform = (egform) form;//直接调用hiberante实现数据持久化getuser(request).setname(egform.getname()); return mapping.findforward(success);} |
上述update方法代码中直接调用了后台数据库操作,带来的缺点是紧密的耦合性,当更新用户资料的需要有更多变化时,将会直接在update中加入更多业务逻辑代码,也就是说,我们的业务逻辑层代码已经完全依赖struts这个表现层技术,万一以后我们选用其它表现层技术替代struts后,将会触及我们业务逻辑层代码。修改后代码如下:
public actionforward update(actionmapping mapping,actionform form,httpservletrequest request,httpservletresponse response)throws exception{ egform egform = (egform)form;contact contact = new contact();beanutils.copyproperties(contact, egform); userservice userservice = servicefactory.create(); userservice.update(contact);return mapping.findforward(success);} |
正如图中所示,一般使用工厂模式涉及到静态类或单态模式,如上述代码中servicefactory.create()可以使用静态或单态模式实现,从而形成客户端单一访问业务逻辑层入口,这样优点有两个:
1. 由于业务逻辑入口是单一的,客户端对业务逻辑访问的可控性强,例如可动态单一入口加入权限检查或其它全局统一功能。jive中权限正是这样实现。可控性强。
2. 客户端代码简洁,作为客户端的表现层技术,如果我们更换了实现技术,修改的代码很少,例如上述代码中,如果不使用struts更换了jsf等,只要拷贝上述两行红字标注的代码。
工厂模式带来的主要缺点是:
1. 当servicefactory实现子类很多时,例如除了userservice外,还有productservice、itemservice、imageservice等等,试图使用一个总入口来涵括这些service会造成过多代码耦合在一个类中,造成facade模式滥用的后果。也就是说,使用工厂模式,扩展性不是很强。
2. 由于使用静态或单态模式,在性能上,容易走入单线程、单并发用户的误区,违背了j2ee多线程并发使用的原则。
二、command模式
command模式可以说解决了上面工厂模式的缺点,command模式将所有的服务都展示给客户端,客户端可以通过特定命令形式直接指定调用后台众多service中任何一种,petstore中web对ejb调用就是使用了command模式实现。
command模式虽然突破了工厂模式单一入口的缺点,但是带来的缺点是易用性不够,command模式代码实现起来不方便,这点可从petstore绕人的webcontaoller、event、action等等众多类中可以看出。
command模式主要问题是可控性不强,如果要为所有service动态增加类似filter等这样通用功能,如权限检查等是非常不方便的。
ejb直接调用实现
我们知道,ejb是业务逻辑层实现的j2ee标准技术,ejb的session bean可以作为service实现,例如上面在update中调用ejb的代码如下:
public actionforward update(actionmapping mapping,actionform form,httpservletrequest request,httpservletresponse response)throws exception { egform egform = (egform)form;contact contact = new contact();beanutils.copyproperties(contact, egform); try{initialcontext ic = new initialcontext();userservicelocalhome ul =ic.lookup("userservice"); userservicelocal userservice =ul.create();userservice.update(contact); }catch(){} return mapping.findforward(success);} |
在客户端表现层是直接调用ejb服务的,这种直接调用的方式类似command模式,但是有两个缺点:
1. 客户端调用业务层实现代码较多,如上述红字行数有4行,客户端代码不简洁。
2. 无法非常自由地为所有service动态增加新的filter之类新功能,当然除了ejb提供的事务机制、分布集群、安全acl等除外,如果你要增加这些新功能,可以通过ejb-jar.xml配置增加。
业务代理模式实现目标
总结上述两种实现的优缺点,衡量一个业务代理模式是否良好有下面几个指标:
1. 业务层所有服务完全展示给客户端。客户端可以完全介入调用。
2. 动态扩展性强,可为整个业务逻辑层动态扩展新的功能。
3. 客户端调用业务层的实现代码必须简洁,至少是可配置的,最大限度降低代码的耦合性。
ioc模式/aop实现
目前,使用ioc模式/aop实现业务代理能够很好地达到上述3个目标,以jdonframework为例:
1. 业务层所有服务完全展示给客户端。客户端可以完全介入调用。而且调用代码简洁,如下:
public actionforward update(actionmapping mapping,actionform form,httpservletrequest request,httpservletresponse response)throws exception{ egform egform = (egform) form;contact contact = new contact();beanutils.copyproperties(contact, egform); userservice userservice = webapputil.getservice("userservice", rerquest);userservice.update(contact); return mapping.findforward(success);} |
上述红字两行代码不但适合调用普通pojo,而且适合调用ejb,具体是什么可以通过jdonframework.xml实现。
1. 通过加入自己的aop拦截器可以为整个业务逻辑层动态扩展新的功能,这部分功能实现不是通过配置实现的,而是使用代码实现:
methodinterceptor myi =new myinterceptor();webapputil.addinterceptor(myi, request); |
有关aop中更复杂的pointcut实现,可以通过获得ioc容器后自己实现:
containerwrapper cw =webapputil.getcontainer(request); |
Java Asp PHP .Net XML C/C++ CGI VB Jsp J2ee J2se J2me EJB Servlet Tomcat Resin Struts Weblogic Eclipse ANT GUI JMS Web servise IDEA Webphere Hibernate Spring Jboss Applet Swing Socket Javamail Perl Ajax P2P 安全 模式 框架 测试 开源 游戏
Windows XP Windows 2000 Windows 2003 Windows Me Windows 9.x Linux UNIX 注册表 操作系统 服务器 应用服务器