`
ldd600
  • 浏览: 102160 次
  • 性别: Icon_minigender_1
  • 来自: 上海
博客专栏
47bb354f-8b5f-3ea6-a206-c7ead38c741c
Hyperic插件开发不完...
浏览量:11109
社区版块
存档分类
最新评论

侦听和处理用户对业务对象改动的简易框架(上)

阅读更多

在用户修改了领域对象的值后,我们有时需要记录下用户的改动。比如对一些关键业务对象的改动有时往往需要发邮件通知客户。有时用户可能想查阅所有历史的改动,甚至有可能会改回原先的值。

领域逻辑关系往往比较复杂,这时我们会使用到ORM Framework。本文以toplink为例,讲述如何利用toplink编写一个完成此功能的简易Framework,我们暂且把它称为ActionMemed

我们先来看一下大体的流程:

l           我们获得用户修改信息通常有两种方式,一种是被动的监听,另一种主动的通知。被动的监听就是framework订阅所关心领域对象的修改,主动通知是application主动的将修改之前和之后的对象通知framework

l           Framework接着从整个对象的树结构中找出用户所关心的某个特定的字段或者字段的组合,生成actionRecordActionRecord是描述用户对领域对象修改的数据结构,会包括用户修改的原因,修改者,修改的时间,修改的字段或者组合,修改前后的值等等信息。

l           ActionRecord生成好之后,会将它记录到DB,发邮件通知用户或者通过JMS通知其他Application

有了基本的概念后,看一下整体的结构:

 

 

 

 

Registry: TopLink上注册ActionListener。一旦在TopLink上检测到业务对象的改动就会调用ActionService,生成ActionRecord并调用相关的ActionRecorder

ActionListenerTopLinkSessionListener,每次会话都会调用。我们在这里实现了preCommit方法,在UnitOfWork提交之前,捕捉用户的所有修改,并从中选取出用户所关心的对象的变动。

ActionService:ActionListenerTopLink中获得到改动的对象,就会调用ActionService生成ActionRecord,并通知相关的Recorder,可能是LogDB。如果用户是通过主动的方式传入新老两个对象就不需要Listener,直接调用ActionService,将新老对象或者新对象和ValueDistiller作为参数传入,

ValueDistiler:根据当前的新对象,萃取出老对象。TopLink就可以根据当前UnitOfWork中的新对象获取原始对象。方法是:

 

public Object getOriginalVersionOfObject(Object workingClone)

 

ExpressionActionMemed相关的配置数据,由ExpressionParser解析出来后就会cache在内存中。这个配置可以是文件,或者DB配置。只要能描述清楚就行。文件配置我们直接利用spring bean

ActionConstructor:ListenerTopLink ChangeSet中拿到的只是有改动的对象。而我们关心的只是对象上某个Field或者它引用的某个对象的Field,比如说EmployeePhoneNumber ListPhoneNumber有个属性是areaCode,可能我们只关心areaCode值的更改,就只需要记录areaCode的更改,并且通知客户。所以我们需要根据用户配置对新老对象进行对比,比较是否有关注的属性被用户更改了。并且构建ActionRecord。比较的方法我们可以用JXpath Xpath的表达能力很强,而且还可以自定义函数,在自定义扩展函数里用户可以对字段进行组合处理,从而生成它们自己想要记录的值。

ActionRecorder:当Action构建完成后,ActionRecorder就要将它通知客户,用JMS发给其他项目或者记录到DB。用户可以配置多个ActionRecorder

MemedEventListener,让用户在ActionRecorder调用之前和之后做一些额外的处理。比如说用户可能在之前对Action的数据结构加入一些定制信息。

 

上面介绍了ActionMemed的流程和相关模块的功能。其实在使用中,特别是一次修改很多业务对象的时候,处理Action时间会有点长,况且Action的处理也并不需要实时。所以Action还需要提供异步处理的功能。

 

 

 

将异步调用的模块图和先前的结构图进行比较会发现有两处不同:

ServiceTask: 实现Java Runnable接口,基本实现类似于先前图中的ActionService

 

ObjectCloner: 如果我们使用TopLink,在异步的情况下,用户当前的UnitOfWork(事务)会先提交,提交之后,从TopLink中萃取的旧对象会被Merge成新对象,这时我们只能提前在UnitOfWork提交之前自己根据Expression的结构深Copy一份出来。

 

ActionAsyncService: 为异步设计的ActionService,利用ValueDistillerUnitOfwork获得当前对象的原始clone,构建ServiceTask,将ServiceTask提交到ThreadPool,当task被执行时,就会调用ActionService,这时的ActionService重用了同步流程中的ActonService

 

在下篇中,将会介绍几个注意点。

下篇地址:http://ldd600.iteye.com/blog/534043

  • 大小: 19.2 KB
  • 大小: 28.3 KB
0
0
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics