J2EE之巅

 

如何在程序中直接使用Spring的工具类

Spring中存在大量的工具类,如:RMI相关的。Spring所提供的 RMI的支持大大简化了RMI的开发难度,不过通常我们都是采用配置的方式,通过标准的spring bean来使用它们,这样虽然简化了开发,但是也限制了一些灵活性。因为bean的属性都是在配置时设定的(如RMI客户端中的服务的URL),而有时我 们需要在运行时生成这些属性,这时其实只要我们直接使用这些工具类就可以了。
要在程序中直接使用RmiProxyFactoryBean,我们就必须了解spring是如何使用这个类为我们生成客户端代理的,然后在程序中使用与spring相同的调用方式。
RmiProxyFactoryBean是一个工厂类,平时我们通过spring获得的并不是这个工厂类的实例,而是用这个工厂类创建的proxy的实例,这个类实现了spring中标准的FactoryBean接口。FactoryBean接口中定义了三个方法:
getObject()
           Return an instance (possibly shared or independent) of the object managed by this factory.
getObjectType()
           Return the type of object that this FactoryBean creates, or
null if not known in advance.
boolean
isSingleton()
           Is the bean managed by this factory a singleton or a prototype?
我们通过getBean获取这类工厂Bean(实现了FactoryBean接口的Bean)时,spring并不会返回工厂类的实例,而是调用工厂类的getObject方法并把方法的返回值返回给我们。
这样你就明白了原来我们获得的RMI的Proxy是通过RmiProxyFactoryBean的getObject方法生成的。
这时你一定认为下面的程序就可以搞定了:
              …
RmiProxyFactoryBean proxy=new RmiProxyFactoryBean();           
              proxy.setServiceInterface(Calculator.class);
              proxy.setServiceUrl(url);
              Calculator client=(Calculator)proxy.getObject();         
              System.out.println(client.add(1,1));
              …
运行程序你会发现上面这段程序并不成功,程序会抛出java.lang.NullPointerException异常。
问题在哪里呢?研究一下你会发现RmiProxyFactoryBean还实现了spring的InitializingBean接口,接口中包含一个方法afterPropertiesSet(),在所有属性注入完成后spring会调用这个方法,因此上面的程序并没有完全正确的模拟spring的调用过程。
修改代码:
RmiProxyFactoryBean proxy=new RmiProxyFactoryBean();           
              proxy.setServiceInterface(Calculator.class);
              proxy.setServiceUrl(url);
              proxy.afterPropertiesSet();
              Calculator client=(Calculator)proxy.getObject();         
              System.out.println(client.add(1,1));
              …
这次终于成功了!

最后,此例告诉大家有时我们可以直接调用spring中的工具类,来完成我们的特殊需求,此时要注意的是正确模拟spring的对bean创建和调用过程。

posted @ 2007-12-26 17:38 超越巅峰 阅读(1344) | 评论 (0)编辑 收藏

Spring2.5的组件自动搜索

http://dev2dev.bea.com.cn/blog/chaocai/200712/spring_osgi_04_719.html

posted @ 2007-12-04 12:50 超越巅峰 阅读(2730) | 评论 (1)编辑 收藏

帮自己的另一个Blog拉拉票

http://dev2dev.bea.com.cn/bbs/ext/dev2devperson/

蔡超

posted @ 2007-11-28 23:00 超越巅峰 阅读(798) | 评论 (5)编辑 收藏

多视图架构文档编写的要点

http://dev2dev.bea.com.cn/blog/chaocai/200710/architecture_24_536.html

posted @ 2007-11-07 20:07 超越巅峰 阅读(843) | 评论 (0)编辑 收藏

黑板模式的常见实现方式

http://dev2dev.bea.com.cn/blog/chaocai/200711/06_623.html

posted @ 2007-11-07 08:57 超越巅峰 阅读(1357) | 评论 (0)编辑 收藏

我的另一个Blog地址

http://dev2dev.bea.com.cn/blog/chaocai/

posted @ 2007-11-05 08:55 超越巅峰 阅读(577) | 评论 (1)编辑 收藏

Facade与边界控制

多层结构是J2EE应用开发的基本模式,很多开发者都会按照多层结构来组织自己的应用(通常分为Facade,Application Service,DAO等层),但是他们往往会选择在不同层上去控制事务和Hibernate Session的边界,可千万不要小看这样的选择它会大大影响程序的可维护性和可复用性。
其实在Facade层来控制事务的边界通常都是最佳选择。我们知道Facade层的粗粒度接口是直接为用户请求提供相应服务的,在典型的J2EE环境中通常使用Session Bean来实现Facade层,并且使用CMT。这时如果有的开发人员在其他层次控制了事务如DAO,由于这些层次通常不会采用EJB实现,所以所使用的事务为容器提供的用户管理事务,根据EJB的事务规范CMT是无法把事务上下文传递到用户管理事务的边界中的,由于J2EE并不支持事务的嵌套,所以当来自Facade的CMT事务遇见DAO的事务时,内部事务将被挂起,这样整个事务的情况,就会和设想的业务逻辑产生很大的差异。
并且有时不同业务逻辑的实现会复用DAO提供多个方法,所以很难控制事务的边界,导致这些方法难以被复用。
对于Hibernate Session,由于存在懒加载的问题,所以开发人员常会预见这样的异常LazyInitializationException。避免这个问题就要求在关闭session前要装载好要使用的对象关系域。而这种逻辑通常只与界面显示内容相关,如果把session的边界控制放置在DAO或者Application Service中就会使业务逻辑的实现要和界面显示逻辑混合在一起,我们必须在这些方法中加载那些界面显示需要的对象关系域。而界面显示是经常变化的,并且业务逻辑会被多个不同的界面所复用,如果这样Application Service,DAO中方法的复用性就会大大降低。
把这些工作放在离表现层最近的Facade中便可以避免这些问题。
注意在其他层次中我们不需要控制session的边界,我们通常采用getCurrentSession()来获得当前事务中的session,记住这个方法必须在事务上下文存在的情况下才可以调用,并且在事务被提交的时候Hibernate会在自动关闭session,所以我们不要显示的关闭session.

posted @ 2007-10-26 10:00 超越巅峰 阅读(1312) | 评论 (0)编辑 收藏

SWF一个简单工作流引擎[支持spring的版本1.3]

SWF一个简单工作流引擎

你是否已经被像JBPM,XFLow等那样的复杂编程和配置搞头昏脑胀;被他们所依赖的大量jar和容器搞得不知所措。
如果这样就试试笔者开发的这个简单工作流引擎吧,配置和编程都很简单,也不依赖任何容器。支持spring的版本。
下载地址:
http://www.blogjava.net/Files/chaocai/swf-beta-1[1].3-bin.zip
内附用户手册
(SWF开发设计:蔡超,北京天融信,chaocai2001@yahoo.com.cn)
 

简介

SWF是一种嵌入式的工作流引擎,它不需要任何应用服务器的支持。SWF使用十分简单,但却可以满足多数流程驱动应用的需求。并且支持和主流j2ee框架整合(spring).

本文介绍如何基于SWF开发流程驱动的应用。

posted @ 2007-10-08 17:03 超越巅峰 阅读(1074) | 评论 (0)编辑 收藏

SWF一个简单工作流引擎

你是否已经被像JBPM,XFLow等那样的复杂编程和配置搞头昏脑胀;被他们所依赖的大量jar和容器搞得不知所措。
如果这样就试试笔者开发的这个简单工作流引擎吧,配置和编程都很简单,也不依赖任何容器。马上会推出支持spring的版本。
下载地址:
http://www.blogjava.net/Files/chaocai/swf-beta-1-bin.zip
内附用户手册
(SWF开发设计:蔡超,北京天融信,chaocai2001@yahoo.com.cn)
 

简介

SWF是一种嵌入式的工作流引擎,它不需要任何应用服务器的支持。SWF使用十分简单,但却可以满足多数流程驱动应用的需求。

本文介绍如何基于SWF开发流程驱动的应用。

posted @ 2007-10-08 10:44 超越巅峰 阅读(2950) | 评论 (10)编辑 收藏

懒对象加载模式

 

问题

随着轻量级持久化框架的流行(如:HibernateJDOJPA),领域对象取代了传统的DTO直接作为值对象,而在这种架构应用的开发过程中,开发人员常会预见这样的异常LazyInitializationException。上述问题是由于Hibernate对于领域对象的关系域对象采取了懒加载策略所导致的(即在关系域被访问时才真正加载创建这些相关对象,Hibernate提供的懒加载策略在很多时候都可以让我的程序获得更高的效率);由于领域对象在脱管的状态下被作为值对象传回显示层,而显示层如果访问了采用懒加载策略加载的关系域,便会导致LazyInitializationException异常。

为了避免这个问题,我们常常会在Façade层的业务方法中加入与特定显示要求相绑定的返回对象初始化过程(即装载那些被懒加载了的关系域对象)。Façade通常是我们用于控制事务边界和完成返回的领域对象脱钩的地方。

1 表现层是易变的这样就会导致连锁反应,大量的代码需要维护,完全违背了面向对象设计的原则,增加了程序的维护成本。

2 并且Façade可能用于支持多种不同的表现层,很难让一个方法满足不同的要求。

OSIVOpen Session in View)结构是一种解决上述问题的方法,这种结构之所以能解决上述问题关键就在于OSIV在表现层中控制Session的打开和关闭,控制事务边界。OSIV虽然简化了应用程序的结构,也避免了LazyInitializationException问题,但是也有很多不足:1.增加了表示层的负责度,2.在响应返回表示层前必须提交事务。3.由于减少了封装层次,表现层直接操作领域对象使得包括性能方面的各种优化更为困难。

解决方案

思考既然表示层知道要显示的信息,即领域对象应该加载哪些相关联的对象。那么我们何不把这个任务交给Façade的调用者(表现层)来完成呢?

不同的表示层可能会有不同的显示策略,利用策略模式(GoF)我们让表示层来注入所需的关系域加载策略实现。

下面便是这个想法的实现:

示例中的领域模型:


图表
1示例中领域对象模型

示例中相关的组件


图表
2示例相关组件

LazyObjectLoader:懒对象加载者接口,其定义如下

来对象加载策略接口

package org.ccsoft;

publicinterface LazyObjectLoader {

    publicvoid loadLazyObjects(Object obj);

}

该接口定义了不同懒对象加载策略实现者要实现的方法,在loadLazyObjects方法中实现对领域对象obj相关的关系域对象进行加载的策略。

OrderItemLoader一种加载策略的实现,用于加载Order对象的关系域对象OrderItem对象

package org.ccsoft;

import java.io.Serializable;

publicclass OrderItem implements Serializable {

   

    private String detail;

    public String getDetail() {

       returndetail;

    }

    publicvoid setDetail(String detail) {

       this.detail = detail;

    }

   

}

OrderMgrFacadeImp: Façade的实现,可以使POJO也可以使Session Bean

package org.ccsoft;

publicclass OrderMgrFacadeImp implements OrderMgrFacade {

    private OrderDAO orderDAO;

    public OrderDAO getOrderDAO() {

       returnorderDAO;

    }

    publicvoid setOrderDAO(OrderDAO orderDAO) {

       this.orderDAO = orderDAO;

    }

    public Order getOrder(int orderId, LazyObjectLoader loader) {

       Order order=orderDAO.getOrder(orderId);

       loader.loadLazyObjects(order);

       return order;

    }

   

}

getOrder方法中我们要求调用者提供了懒对象装载策略的实例用于装载那些调用者要用到的关系域对象。注意该示例是通过spring实现的,利用spring AOP完成事务管理,事务的边界在Façade中方法上,当方法执行结束,事务业务将结束,并且Hibernate会自动关闭session,我们看到getOrder方法中在事务结束前调用了懒对象装载策略,从而按照调用者的要求装载了调用者所需的关系域对象。

该模式的优点

1 将领域对象的处理逻辑与显示层的显示逻辑完全分离,提高了代码的可维护性和可扩展性

该模式的不足

1 要求显示层的开发者,了解懒加载的情况

2 增加了代码的复杂性

________________________________________________________________________

SCEA SCBCD MCSD
IBM Certified Specialist RUP
IBM Certified Solution Designer OOA&D UML v2
北京天融信软件架构师
SUN,Microsoft培训中心特邀高端教师
常年提供架构咨询服务
chaocai2001@yahoo.com.cn 010-82776427



posted @ 2007-09-20 21:28 超越巅峰 阅读(1537) | 评论 (1)编辑 收藏

仅列出标题
共6页: 上一页 1 2 3 4 5 6 下一页 

导航

统计

常用链接

留言簿(12)

随笔分类(54)

随笔档案(59)

文章分类(2)

文章档案(1)

相册

搜索

积分与排名

最新评论

阅读排行榜

评论排行榜