什么是业务代理模式(buiness proxy)? 在JEE系统中一般划分为表现层和业务逻辑层为实现表现层和业务逻辑层之间的最大限度解耦引入业务代理模式这样当表现层或业务逻辑层具体实现技术发生时对彼此的影响很小当然如果希望实现完全解耦我们可以使用消息系统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(egFormgetName()); return mappingfindForward(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(); pyProperties(contact egForm); UserService userService = ServiceFactorycreate(); userServiceupdate(contact); return mappingfindForward(SUCCESS); } 上述修改后代码中我们将业务逻辑包装在UserService的一个子类中实现作为客户端我们使用工厂模式创建UserService对象这样的好处是我们不必在update方法中耦合UserService的具体子类也许UserService的子类是UserServiceHibernate或UserServiceEJB等 使用工厂模式实现了表现层和业务层的解耦这是早期很多系统的架构实现但是这样还是带来很多问题我们下面比较一下几种实现方式 工厂模式优缺点 首先我们总结一下上述代码使用了工厂模式所带来的好处 正如图中所示一般使用工厂模式涉及到静态类或单态模式如上述代码中ServiceFactorycreate()可以使用静态或单态模式实现从而形成客户端单一访问业务逻辑层入口这样优点有两个 由于业务逻辑入口是单一的客户端对业务逻辑访问的可控性强例如可动态单一入口加入权限检查或其它全局统一功能Jive中权限正是这样实现可控性强 客户端代码简洁作为客户端的表现层技术如果我们更换了实现技术修改的代码很少例如上述代码中如果不使用Struts更换了JSF等只要拷贝上述两行红字标注的代码 工厂模式带来的主要缺点是 当ServiceFactory实现子类很多时例如除了UserService外还有ProductServiceItemServiceImageService等等试图使用一个总入口来涵括这些Service会造成过多代码耦合在一个类中造成Facade模式滥用的后果也就是说使用工厂模式扩展性不是很强 由于使用静态或单态模式在性能上容易走入单线程单并发用户的误区违背了JEE多线程并发使用的原则 Command模式 Command模式可以说解决了上面工厂模式的缺点Command模式将所有的服务都展示给客户端客户端可以通过特定命令形式直接指定调用后台众多Service中任何一种Petstore中Web对EJB调用就是使用了Command模式实现 Command模式虽然突破了工厂模式单一入口的缺点但是带来的缺点是易用性不够Command模式代码实现起来不方便这点可从Petstore绕人的WebContaollerEventAction等等众多类中可以看出 Command模式主要问题是可控性不强如果要为所有Service动态增加类似Filter等这样通用功能如权限检查等是非常不方便的 EJB直接调用实现 我们知道EJB是业务逻辑层实现的JEE标准技术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(); pyProperties(contact egForm); try{ InitialContext ic = new InitialContext(); UserServiceLocalHome ul = iclookup(UserService); UserServiceLocal userService = ulcreate(); userServiceupdate(contact); }catch(){ } return mappingfindForward(SUCCESS); } 在客户端表现层是直接调用EJB服务的这种直接调用的方式类似Command模式但是有两个缺点 客户端调用业务层实现代码较多如上述红字行数有行客户端代码不简洁 无法非常自由地为所有Service动态增加新的Filter之类新功能当然除了EJB提供的事务机制分布集群安全ACL等除外如果你要增加这些新功能可以通过ejbjarxml配置增加 业务代理模式实现目标 总结上述两种实现的优缺点衡量一个业务代理模式是否良好有下面几个指标 业务层所有服务完全展示给客户端客户端可以完全介入调用 动态扩展性强可为整个业务逻辑层动态扩展新的功能 客户端调用业务层的实现代码必须简洁至少是可配置的最大限度降低代码的耦合性 Ioc模式/AOP实现 目前使用Ioc模式/AOP实现业务代理能够很好地达到上述个目标以JdonFramework为例 业务层所有服务完全展示给客户端客户端可以完全介入调用而且调用代码简洁如下 public ActionForward update(ActionMapping mapping ActionForm form HttpServletRequest request HttpServletResponse response) throws Exception { EgForm egForm = (EgForm) form; Contact contact = new Contact(); pyProperties(contact egForm); UserService userService = WebAppUtilgetService(UserService rerquest); userServiceupdate(contact); return mappingfindForward(SUCCESS); } 上述红字两行代码不但适合调用普通POJO而且适合调用EJB具体是什么可以通过jdonframeworkxml实现 通过加入自己的AOP拦截器可以为整个业务逻辑层动态扩展新的功能这部分功能实现不是通过配置实现的而是使用代码实现 MethodInterceptor myI = new MyInterceptor(); WebAppUtiladdInterceptor(myI request); 有关AOP中更复杂的pointcut实现可以通过获得Ioc容器后自己实现 ContainerWrapper cw = WebAppUtilgetContainer(request); 这样可以为用户提供非常自由的面向微容器编程的基础这比同样的Ioc/AOP实现Spring开源框架提供的自由度更广更加透明 更加重要的是JdonFramework只是真正绅士地完成业务代理模式不过多地介入业务层业务层相关配置是使用配置文件实现需要插入的通用功能是使用代码实现而Spring目前版本则是将两者混淆在一起 |