<%@ page contentType="text/html; charset=gb2312"%> 怎样用spring来重构这样一个遗留系统?
网站公告:   ◆北天JAVA技术网热情为java爱好者服务,本网内容包括JAVA(JSP、servlet、EJB、webservice、j2ee、javabean、应用服务器、JavaScript),数据库(MYSQL、SQL Server、Sybase、Oracle、DB2、数据库综合知识),设计研究(设计模式、Struts、Spring、Hibernate、设计框架、设计综合知识),WEB2.0新技术(主要介绍AJAX),以及各种技术的入门、实例、例子等等,欢迎各位多来坐坐!◆  诚邀各位JAVA爱好者加盟!◆  本网站内容丰富,更新快,保证每周20篇以上!  
加入收藏
设为首页
联系站长
承接项目
  相关资源:网站首页 | 免费培训学院 | 技术论坛 | JAVA聊天室 | 作家专栏 | 开发工具 | 认证考试 | 会员俱乐部
  JAVA技术初学者园地 | jsp与servlet | javascript | Java源代码 | EJB | web service | 应用服务器 | JAVA综合知识
  设计研究设计模式 | 设计框架 | Struts | Spring | Hibernate | 开源项目 | 面向对象设计 | 设计综合知识
  数 据 库MYSQL | SQL Server | Sybase | Oracle | DB2 | Informix | Access | 数据库综合知识
  其他资源:AJAX新技术 | 网站开发 | ERP软件 | OA办公软件 | 商业智能BI | 开发综合知识 | 承接项目 | 项目试用

 
 
怎样用spring来重构这样一个遗留系统?
     发布者: 发布时间:2007-07-27

我们现在经手的这个系统,有这么一个非常非常核心的类:
ImplFactory。它有一个非常非常核心的方法:

代码
  1. ImplFactory.newClass(Class type, Object[] args);  

这个方法什么意思呢?基本上和调用new type(arg1, arg2, ...)差不多。只不过是动态的,类型不安全的。
为什么要这么做呢?其本意是,后面有一个ImplFactory.properties文件,当调用newClass(MyType.class, new Object[]{a,b,c})的时候,ImplFactory会先检查ImplFactory.properties,如果发现MyType有个子类被登记了,就用那个子类,否则就用MyType本身。无论如何,args都会被作为构造函数的参数传入。

有些对newClass()的调用非常复杂冗长。比如系统某些地方要对某个service包裹一层logging支持,那么要先用newClass找到logger instance,然后用newClass找到这个service,最后还要用newClass来把这个logger和service封装到一个LoggedService(或者子类)中。

这个系统的另外一个讨厌的地方是,到处出现的appId和sessionId两个变量。这两个变量根据程序的上下文值会不同。而在调用ImplFactory.newClass的时候50%的情况需要传递这两个变量,很烦琐。

现在,考虑用spring重构。难点为:

    1。希望能够暂时不动ImplFactory.properties文件。因为大家(包括客户)已经习惯于用它了。最好能在spring.xml里面写:
    代码
    1. <include properties="ImplFactory.properties"/>   

    然后额外的一些比较复杂的组装比如logging,用spring xml来搞。
    2。希望保留系统原来的缺省类型语义,配置文件可以只用来配置customization。有时候如果newClass(MyClass.class)的这个MyClass不需要提供一个子类,可以直接用new MyClass(),而不是要求必须在spring xml里面配置MyClass。
    3。无论spring如何配置,希望允许参数从外部传递进来。newClass(MyClass.class, new Object[]{a,b})希望能够把a和b传递给被spring配置的组建类。
    4。appId和sessionId的传递很烦琐,希望能够把它们作为所有组件的全局变量。而不用每次都传递。(这样可以减少多于一半的传递额外参数的需要了)而如果作为全局变量,希望不同上下文的不同值能够被正确反映,而且线程安全,而且不严重影响并发性。


最后,如果这些需求都能做到,我就可以用dynamic proxy,那container实现一个强类型的ServiceFactory,最终客户的调用代码会变成:
代码
  1. MyClass mc = factory.getMyClass();   
  2. MyService service = factory.getMyService(a, b);   

然后再把ServiceFactory注射到使用ImplFactory的类里面来代替它,就算搞定了。

我是暂时还没有发现用spring怎么实现这些需求,用yan倒是可以。正好借着spring讨论的热乎劲儿,请spring的专家给鉴定鉴定。




声明:JavaEye文章版权属于作者,受法律保护。没有作者书面许可不得转载。若作者同意转载,必须以超链接形式标明文章原始出处和作者。
相关文章:   关于spring 2.0自定义xml 标记 (二 如何实现)   关于spring 2.0自定义xml 标记 (一 主要的相关类)
评论    共 19 条 发表评论
抛出异常的爱     2006-10-31 22:03

我们也正想大规模重构系统
把ejb从系统中踢出去
但是一点头絮都没有
如果可能把你的过程写成blog好不好
PS:可不可以加我为好友

nihongye     2006-10-31 23:46

1,2,3这么理解?

调用: ImplFactory.newClass(Class type, new Object[]{a,b});

ImplFactory.properties里面有
MyType=DefaultMyTypeImpl.class

spring.xml里(这个配置是随手写的):
<bean id="任意" class="DefaultMyTypeImpl">
<constructor-arg index="0">${0}</constructor-art>
<constructor-arg index="1">${1}</constructor-art>
<constructor-arg index="2">
<ref bean="其它spring组件"/>
</constructor-art>
</bean>

这些组件要注入其它bean吗?

ajoo     2006-11-01 01:36

nihongye 写道

1,2,3这么理解?

调用: ImplFactory.newClass(Class type, new Object[]{a,b});

ImplFactory.properties里面有
MyType=DefaultMyTypeImpl.class

spring.xml里(这个配置是随手写的):
<bean id="任意" class="DefaultMyTypeImpl">
<constructor-arg index="0">${0}</constructor-art>
<constructor-arg index="1">${1}</constructor-art>
<constructor-arg index="2">
<ref bean="其它spring组件"/>
</constructor-art>
</bean>

这些组件要注入其它bean吗?


比如调用newClass(com.mycom.MyType.class, new Object[]{a,b})的时候,如果properties文件没有对com.mycom.MyType登记,那么直接调用new MyType(a,b);
而如果有,比如:
com.mycom.MyType=com.mycom.MySubType
那么就new com.mycom.MySubType(a,b)

最终当这个properties文件不用了,或者我们选择在appcontext.xml中配置比较复杂的组件,比如你的例子中的那个,希望客户接口不变。还有,如果这个DefaultMyTypeImpl需要用appId,希望能这么写(或者等价的方法)

代码
  1. <bean id="任意" class="DefaultMyTypeImpl">  
  2.     <constructor-arg index="0">${appId}</constructor-art>  
  3.     <constructor-arg index="1">${0}</constructor-art>  
  4.     <constructor-arg index="2">${1}</constructor-art>  
  5.     <constructor-arg index="3">  
  6.        <ref bean="其它spring组件"/>  
  7.     </constructor-art>  
  8. </bean>  

这个组件有可能注入其它bean的,至少我们不希望被剥夺这个可能性。

nihongye     2006-11-01 02:09

哦,明白了,要学习一番spring才知道,现在只知道从ApplicationContext下手,但里面那套复杂的wire,parent,child context不知道是怎样的。

ajoo     2006-11-01 05:25

说明一下,

1不是必要的。如果不好弄,大不了我自己写代码读这个property文件然后自己登记appcontext。关键是2,3,4。如果做不到,spring就只能被枪毙了。

关于3,柞一想似乎不合理。难道要求所有的子类都必须接受a,b两个参数?可仔细一想,存在的就有其合理性。也许不是所有的实现都必然需要接受这两个参数,但是至少典型的实现都要这两个参数。

我用yan实现这个功能的时候,如果配置的实现类不需要这两个参数,也没关系,程序会自动忽略传进来的参数。

从spring的BeanFactory接口来看,目前似乎做不到。它只有getBean(beanName),而没有办法额外传递参数。

所以目前我只实现了yan的prototype,spring和pico都还没着落呢。

hgbjava     2006-11-01 10:58

自己扩展一个spring的BeanFactory类,在afterpropertyset方法里添加自己想要的参数咯!

ajoo     2006-11-01 11:09

hgbjava 写道
自己扩展一个spring的BeanFactory类,在afterpropertyset方法里添加自己想要的参数咯!

有点怀疑你自己都不知道自己在说什么。
afterpropertiesset是对象已经创建了之后才调用的,怎么可能处理构造函数的参数?
扩展BeanFactory又能和afterpropertieset扯上什么联系?

hgbjava     2006-11-01 11:22

ajoo 写道
hgbjava 写道
自己扩展一个spring的BeanFactory类,在afterpropertyset方法里添加自己想要的参数咯!

有点怀疑你自己都不知道自己在说什么。
afterpropertiesset是对象已经创建了之后才调用的,怎么可能处理构造函数的参数?
扩展BeanFactory又能和afterpropertieset扯上什么联系?

写一个spring的FactoryBean,在配置文件里可以随意配置你需要的参数,在这个factorybean中再去创建你实际需要的对象,这只不过是可以实现从配置文件里读取属性而已。

nihongye     2006-11-01 11:39

引用
从spring的BeanFactory接口来看,目前似乎做不到。它只有getBean(beanName),而没有办法额外传递参数。

所以目前我只实现了yan的prototype,spring和pico都还没着落呢


我的思路是这样的,实现一个称为
ThreadSafeApplicationContext的context
ImplFactory的实现是这样的:
context.register( type,args );
context.register( "sessionId",sessionId );
return context.getBean(type);
另外:spring再怎么整也比不了yan的设计啊...哈哈。

ajoo     2006-11-01 11:55

nihongye 写道
引用
从spring的BeanFactory接口来看,目前似乎做不到。它只有getBean(beanName),而没有办法额外传递参数。

所以目前我只实现了yan的prototype,spring和pico都还没着落呢


我的思路是这样的,实现一个称为
ThreadSafeApplicationContext的context
ImplFactory的实现是这样的:
context.register( type,args );
context.register( "sessionId",sessionId );
return context.getBean(type);
另外:spring再怎么整也比不了yan的设计啊...哈哈。

能不能具体解释一下,这个args是怎么用到每个bean上去的?

我们现在经手的这个系统,有这么一个非常非常核心的类:
ImplFactory。它有一个非常非常核心的方法:

代码
  1. ImplFactory.newClass(Class type, Object[] args);  

这个方法什么意思呢?基本上和调用new type(arg1, arg2, ...)差不多。只不过是动态的,类型不安全的。
为什么要这么做呢?其本意是,后面有一个ImplFactory.properties文件,当调用newClass(MyType.class, new Object[]{a,b,c})的时候,ImplFactory会先检查ImplFactory.properties,如果发现MyType有个子类被登记了,就用那个子类,否则就用MyType本身。无论如何,args都会被作为构造函数的参数传入。

有些对newClass()的调用非常复杂冗长。比如系统某些地方要对某个service包裹一层logging支持,那么要先用newClass找到logger instance,然后用newClass找到这个service,最后还要用newClass来把这个logger和service封装到一个LoggedService(或者子类)中。

这个系统的另外一个讨厌的地方是,到处出现的appId和sessionId两个变量。这两个变量根据程序的上下文值会不同。而在调用ImplFactory.newClass的时候50%的情况需要传递这两个变量,很烦琐。

现在,考虑用spring重构。难点为:

    1。希望能够暂时不动ImplFactory.properties文件。因为大家(包括客户)已经习惯于用它了。最好能在spring.xml里面写:
    代码
    1. <include properties="ImplFactory.properties"/>   

    然后额外的一些比较复杂的组装比如logging,用spring xml来搞。
    2。希望保留系统原来的缺省类型语义,配置文件可以只用来配置customization。有时候如果newClass(MyClass.class)的这个MyClass不需要提供一个子类,可以直接用new MyClass(),而不是要求必须在spring xml里面配置MyClass。
    3。无论spring如何配置,希望允许参数从外部传递进来。newClass(MyClass.class, new Object[]{a,b})希望能够把a和b传递给被spring配置的组建类。
    4。appId和sessionId的传递很烦琐,希望能够把它们作为所有组件的全局变量。而不用每次都传递。(这样可以减少多于一半的传递额外参数的需要了)而如果作为全局变量,希望不同上下文的不同值能够被正确反映,而且线程安全,而且不严重影响并发性。


最后,如果这些需求都能做到,我就可以用dynamic proxy,那container实现一个强类型的ServiceFactory,最终客户的调用代码会变成:
代码
  1. MyClass mc = factory.getMyClass();   
  2. MyService service = factory.getMyService(a, b);   

然后再把ServiceFactory注射到使用ImplFactory的类里面来代替它,就算搞定了。

我是暂时还没有发现用spring怎么实现这些需求,用yan倒是可以。正好借着spring讨论的热乎劲儿,请spring的专家给鉴定鉴定。


(转载文章请保留出处:北天JAVA技术网(www.java114.com))
 
更多精彩文章:
在Java程序中实现高精度打印
类Excel报表设计器标准
一个使用JAVA xmlencoder 例子
探讨Java与Ruby语言迁移时的安全性
用纯JAVA语言编程读取MAC地址的实现
用AJAX编写用户注册时的应用实例
 
最近评论:
        
你曾悄悄的来过!
wow gold,wow gold,wow gold,ffxi gil max(2466)
        
冰封的往事!
wow power leveling,wow gold,wow power leveling,wow gold max(5737)
        
冰封的往事!
wow power leveling,wow gold,WoW Gold,wow gold max(6803)
        
冰封的往事!
wow power leveling,wow gold,WoW Gold,wow gold max(1585)
        
冰封的往事!
wow power leveling,wow gold,WoW Gold,wow gold max(7566)
        
冰封的往事!
wow power leveling,wow gold,WoW Gold,wow gold max(5691)
        
飞舞的传奇!
传世私服,传世私服.传奇世界私服传奇世界私服,传世私服传世私服, 传奇世界私服传奇世界私服.传奇私服传奇私服. max(5983)
        
标 题:   
内 容:   
 
                                  
 
免责声明:该文章由网友发表,如果对您造成侵权,请联系站长

首页 - 承接项目 - 网站地图 - 联系我们 -
版权所有北天JAVA技术工作室 ICP证号:粤ICP备06079815号