分类:
2008-09-09 15:17:17
作者将在这篇文章中分享他在这个试验中的想法和发现。作者将清晰的说明他是怎样用Spring组件替换参考应用中的单态注册,JDBC代码,和web的前后端层。作者也会描述他遇到的一个问题还有他是怎样来解决它的。
叫我来参加会议晚了,就是这次的Spring框架会议。对于你们后来的人来讲,Spring已经是一个在Apache 2.0许可下发布的基础构造代码库。它的核心是一个反转控制容器,在容器的外部开发组已经创建了JDBC和JMS代码的样板文件模板,一个web MVC框架,和其他组件。
我之所以参加这个会议晚是因为我不管Spring的成熟度和公开度,我都对它花了很长的时间进行了测试。我的问题是:"Spring到底能给我带来什么?",为了找到答案,我用Spring的组件替换了现有的一个应用的内脏。通过这次替换我懂得了:我在很早以前就应该用Spring了;应用程序的代码已经没有以前那么混乱了,调试和扩展也更加容易,并且变的更轻因为我能够开发一些通用的辅助代码来配合Spring。
我将在这篇文章中分享我在这个试验中的想法和发现。我将清晰的说明我是怎样用Spring组件替换参考应用中的单态注册,JDBC代码,和web的前后端层。我也会描述我遇到的一个问题还有我是怎样来解决它的。
接下来的内容不需要你是一个Spring的专家,我会在后面给出Spring资源链接。样例代码在Linux上Spring 1.2.X和JDK1.5.0_07下已通过测试。
原始(旧的)代码
我不想通过制作一个鲜活的应用来进行试验,所以我从另外一篇文章中摘录下我的测试程序。这是一个有2个servlet页面控制器作为入口点的简单的java web应用。servlets通过DAO的方式访问数据库,DAO从本地数据源取得数据库链接。关联对象通过单态注册方式来相互取得。具体有:
SimpleDAO: 从数据库读出和写入信息对象
DbUtil: 方便程序使用JDBC ResultSets, Connections等等。
ObjectRegistry: 单态注册类,对象之间可以通过它彼此取得。
SetupDataSourceContextListener: 设置JDBC数据源
SetupDBContextListener: 预备(植入的)数据库
GetDataServlet: 页面控制器用来显示数据
PutDataServlet: 页面控制器用来数据
这是一个非常简单的应用程序,但它是完全独立的并且展现了一个多层应用程序的行为。这个小型试验的一些观测资料可用于由真实世界转换的工程应用中。
修改内脏:对象注册
首先来分析ObjectRegistry类,它是关系型对象粘合层。
package pool_test.util ;
public class ObjectRegistry {
private static ObjectRegistry _instance = new ObjectRegistry() ;
public static ObjectRegistry getInstance(){
return( _instance ) ;
}
private Map _singletons ;
public void put(final String key , final Object obj){
_singletons.put( key , obj ) ;
}
public Object get( final String key ){
return( _singletons.get( key ) ) ;
}
}
ObjectRegistry 实际上是一个String:Object键值对的一个Map.你可以将一个对象注册在一个地方(put()方法),然后在另外的地方得到这个对象(get()方法)。用注册可以削弱对象依赖因为代码可以仅仅通过它的通用类型(接口或超类)和查找关键字得到一个对象。而细节-实现,实例化和配置-就留给这段调用put()方法对象的代码。
它能工作,而且我发现它工作比较频繁,但它并不完美。缺少put()或者将它放错地方可能会引起空指针错误或栈溢出错误。你必须跟踪对象被存储注册的次序,为了确保你不会试图取的一个不存在的对象。像我在这做的一样,在小的应用中用ContextListener(一个监听器)处理实例化命令,但是在一个大的应用中可能就需要你努力去避免一些问题。
旧的单态注册的另一个问题是暴露的put()操作是java调用?意思是说:一个存储的对象实现的变更需要重新编译注册类-比如为了测试存根你想替换基于数据库的DAO。我以前犯过一个小错误,产品应用中用了DAO 的stub(这里不知道译成什么意思好?)。在一个比较大的应用中,它可能很难捕获到,因为它被隐藏在代码里了。
写点Spring代码就能处理这些缺点。这是新的注册类:
package pool_test.util ;
import org.springframework....ApplicationContext ;
import org.springframework....ClasspathXMLApplicationContext ;
public class ObjectRegistry {
private ApplicationContext _singletons ;
private ObjectRegistry(){
_singletons = new ClassPathXmlApplicationContext(
new String[] { "spring-objectregistry.xml" }
);
}
public Object get( final String key ){
return( _singletons.getBean( key ) ) ;
}
}
[1]