论坛首页 Java企业应用论坛

Domain injection with AOP

浏览 31806 次
该帖已经被评为精华帖
作者 正文
   发表时间:2005-09-01  
partech 写道

不太明白,为什么domain object不能有共同的父类?tell me why.
假如domain object因为都继承了父类DomainObject,而使得实现domain object的生命周期管理能够单点维护,有什么理由不这样干呢?


因为希望我们的aspect是通用的,我们不希望对客户使用的DomainObject做出任何假设,假设或依赖越多,移植性就越差,带来的潜在问题也越多。
其实用ApplicationContext也是同样的道理,在我们的应用程序里的domain object使用ApplicationContext有没有问题?其实假如这个应用只是针对某个特定的需求,假如我们不追求移植性,使用ApplicationContext也完全没有错。
但是Spring里为什么鼓励我们尽量不要依赖ApplicationContext呢?为什么那么强调non-invasive呢?想想原因吧。

我在设计这个aspect时当然希望它可以在任何环境下都可以使用,那么这些“任何环境”的domain object有共同的父类吗?我们根本没法假设。
如果这个系统是以前就设计好的,那就更没办法,难道让用户修改所以的domain object,让它继承一个公有的父类?

所以我认为设计原则应该是这样的:
1、如果我只希望做一个应用程序,绝对不会被人调用,并肯定不会移殖,那么我们继承一个父类,使用ApplicationContext都可以。毕竟没有设计是完美的。
2、如果我要写一个framework,或者让大家都要用的类(比如我写的aspect),那么就对应用的代码做尽量少的假设,尽量让它通用。虽然我的aspect拿到其实系统里还有要改代码(主要是pointcut的定义),但是至少应用系统自身不需要修改代码(比如让它去继承某个类)。

当然我这里也做了假设,假设我们调用DAO的时候使用get方法,而不是 instance变量,我认为这是良好的编程习惯。当然你可以有不同的观点
0 请登录后投票
   发表时间:2005-09-01  
myace 写道
使用“EO/EI”模式,可以摆脱对DAO接口的依赖,最终的调用方法如“((DA
O)customer.getAdapter(DAO.class)).save()”,如果使用JDK5的泛型的画就更好了,可以向这样调用“customer.getAdapter(DAO.class).save()”。

还是不明白,为什么这样就可以摆脱对DAO的依赖了?你现在的实现方法至少依赖了IAdaptable和DAO。
而且你现在用的DAO.class是类还是接口?
我的感觉是具体的类。假如是具体的类的话,所有Spring所提倡的depency injection的意义都不存在了,因为我们在代码里依赖了具体的类,而不是接口。

drliujia 写道

其实本质上都差不多的,aspectj也就是让代码好看点,把我们不愿意看到的对domain object增强的部分给分离到了aspect里面,编译后的class不还是乱成一团?  

呵呵,这个观点好象有点奇怪。整个AOP,整个设计模式,整个面向对象设计的目标都是为了让代码好看点,而不是让编译后的class好看点。
0 请登录后投票
   发表时间:2005-09-01  
xiecc 写道
partech 写道

不太明白,为什么domain object不能有共同的父类?tell me why.
假如domain object因为都继承了父类DomainObject,而使得实现domain object的生命周期管理能够单点维护,有什么理由不这样干呢?


因为希望我们的aspect是通用的,我们不希望对客户使用的DomainObject做出任何假设,假设或依赖越多,移植性就越差,带来的潜在问题也越多。
其实用ApplicationContext也是同样的道理,在我们的应用程序里的domain object使用ApplicationContext有没有问题?其实假如这个应用只是针对某个特定的需求,假如我们不追求移植性,使用ApplicationContext也完全没有错。
但是Spring里为什么鼓励我们尽量不要依赖ApplicationContext呢?为什么那么强调non-invasive呢?想想原因吧。

我在设计这个aspect时当然希望它可以在任何环境下都可以使用,那么这些“任何环境”的domain object有共同的父类吗?我们根本没法假设。
如果这个系统是以前就设计好的,那就更没办法,难道让用户修改所以的domain object,让它继承一个公有的父类?

所以我认为设计原则应该是这样的:
1、如果我只希望做一个应用程序,绝对不会被人调用,并肯定不会移殖,那么我们继承一个父类,使用ApplicationContext都可以。毕竟没有设计是完美的。
2、如果我要写一个framework,或者让大家都要用的类(比如我写的aspect),那么就对应用的代码做尽量少的假设,尽量让它通用。虽然我的aspect拿到其实系统里还有要改代码(主要是pointcut的定义),但是至少应用系统自身不需要修改代码(比如让它去继承某个类)。

当然我这里也做了假设,假设我们调用DAO的时候使用get方法,而不是 instance变量,我认为这是良好的编程习惯。当然你可以有不同的观点

继承父类,使用Aspect inter-type的declare parents统一来做,哪有什么移植性的问题?
0 请登录后投票
   发表时间:2005-09-02  
引用
如果你们知道UnitOfWork用法的话,就再也不想多看一眼DAO了。

下面的一个草案,虽说现在可以改进的更好,但思想还是可以使用的。
http://forum.iteye.com/viewtopic.php?t=13594




hibernate通过一级缓存在事务结束的时候session flush是不是和UnitOfWork差不多?
0 请登录后投票
   发表时间:2005-09-02  
xiecc 写道
myace 写道
使用“EO/EI”模式,可以摆脱对DAO接口的依赖,最终的调用方法如“((DA
O)customer.getAdapter(DAO.class)).save()”,如果使用JDK5的泛型的画就更好了,可以向这样调用“customer.getAdapter(DAO.class).save()”。

还是不明白,为什么这样就可以摆脱对DAO的依赖了?你现在的实现方法至少依赖了IAdaptable和DAO。
而且你现在用的DAO.class是类还是接口?
我的感觉是具体的类。假如是具体的类的话,所有Spring所提倡的depency injection的意义都不存在了,因为我们在代码里依赖了具体的类,而不是接口。

drliujia 写道

其实本质上都差不多的,aspectj也就是让代码好看点,把我们不愿意看到的对domain object增强的部分给分离到了aspect里面,编译后的class不还是乱成一团?  

呵呵,这个观点好象有点奇怪。整个AOP,整个设计模式,整个面向对象设计的目标都是为了让代码好看点,而不是让编译后的class好看点。


这里的DAO是个接口,或许应当写成IDAO,Customer可以有自己的DAO实现比如CustomerDAO。的确Customer依赖IAdaptable但是这没有什么负作用。实际上关注的不仅仅是DAO的问题,除了DAO还有很多的方面,我们不希望Customer类直接对其依赖。这可能是分工上面的问题,比如业务模型的维护和DAO类的维护工作是两组人;也可能是分层上的问题,比如客户端是基于Swing的,这样有些对服务器端资源依赖的方法不能够写到域对象中。但是又希望能够从OOA到OOD又一个较平滑的过渡,减少分工、分层对设计的影响,这样使用扩展适配器可能更为合适。
0 请登录后投票
   发表时间:2005-09-02  
partech 写道
继承父类,使用Aspect inter-type的declare parents统一来做,哪有什么移植性的问题?

呵呵,这个我倒没想到过,这样确实没有移殖性的问题。
但是请告诉我你的父类的单点维护是怎么做的?
要知道我们是无法控制domain object的初始化的,例如我们用hibernate查询返回一组对象时,这些对象的创建是在hibernate里用reflection来创建的,难道我们要求大家在查完之后强制调用父类的init方法?(当然用interceptor是可以的,这就是Rod Johnson写的DependencyInjectionInterceptorFactoryBean,但是用了这个之后似乎根本就不需要AOP了,所以如果使用hibernate并且项目之前未引入AOP的话还是该用interceptor)。

如果对象的生命周期不归我们控制,那么我用get方法进行多点维护无疑是最好的方法,至少它有一个好处是单点维护甚至interceptor达不到的:lazy load。而且我在get之前都做了判断,只要inject过一次以后就不用再做了,因此效率也不是问题。
0 请登录后投票
   发表时间:2005-09-02  
xiecc 写道
partech 写道
继承父类,使用Aspect inter-type的declare parents统一来做,哪有什么移植性的问题?

呵呵,这个我倒没想到过,这样确实没有移殖性的问题。
但是请告诉我你的父类的单点维护是怎么做的?
要知道我们是无法控制domain object的初始化的,例如我们用hibernate查询返回一组对象时,这些对象的创建是在hibernate里用reflection来创建的,难道我们要求大家在查完之后强制调用父类的init方法?(当然用interceptor是可以的,这就是Rod Johnson写的DependencyInjectionInterceptorFactoryBean,但是用了这个之后似乎根本就不需要AOP了,所以如果使用hibernate并且项目之前未引入AOP的话还是该用interceptor)。

如果对象的生命周期不归我们控制,那么我用get方法进行多点维护无疑是最好的方法,至少它有一个好处是单点维护甚至interceptor达不到的:lazy load。而且我在get之前都做了判断,只要inject过一次以后就不用再做了,因此效率也不是问题。

麻烦看看,俺前面说的草案,在实现中domain object生命周期的控制只需要依赖DomainObject。
草案可以改进的地方之一,就是变更继承DomainObject,在LifeCycle aspect中加入:
declare parents Domain.Root.* extends DomainObject
...
0 请登录后投票
   发表时间:2005-09-02  
partech 写道
麻烦看看,俺前面说的草案,在实现中domain object生命周期的控制只需要依赖DomainObject。

嗯,是我疏忽了,没有仔细看你的草案。不过我觉得你最好先把你的草案整理成文档,并不是所有人都有耐心看你的源代码的。

大致看了一下,想法可能还比较粗浅。你好象是想实现Martin Fowler那本书上的Unit of Work,但是用aspectJ来管理这些Domain Object的生命周期。你现在要求所有类都继承 DomainObject类,当然用aspectJ的Declare Parent是可以让这些类不用在代码层继承DomainObject。

但是我不知道你设计的目标是什么,是要自己做一个O/R Mapping工具吗?如果真的能做出来的话倒是可以为中国的开源软件业增光啊。希望你能成功!如果真有这个想法我也想贡献一点力量。至少我们可以看一下用AOP的力量是不是可以把O/R Mapping的实现变得比hibernate更简单,更高效。

显然如果是我们自己实现的持久层,那么这个Domain Object的生命周期都是受我们控制的,但是现在我们讨论的是通用的Domain Object。它可能是Hibernate,可能是EJB或其它O/R Mapping工具,或者是直接用SQL语句,这些不同产品的Domain Object的生命周期是不同的,我们没用办法从中抽取它们生命周期的共性。也许我可以用interceptor来解决hibernate的生命周期问题,但是JDO呢?我们可能要实现另一个完全不同的interceptor。在这种情况下,用get作为pointcut显然比domain Object初始化的时候做为它的pointcut更为合适。
0 请登录后投票
   发表时间:2005-09-02  
你真有眼光,我的草案能发展成另一个ORM工具!
不是拉,俺的Aspect会使用现成的ORM工具。
在UnitOfWork.commit()中,将变化的DomainObject通过ORM工具提交到
数据库中。使用UnitOfWork还有一个优点,就是DomainObject的持久化只
在这里出现,你甚至可以通过接口来适配不同的ORM框架。

我没看错吧,你说的是通用的Domain Object麽?生命周期同hibernate,EJB或其它O/R Mapping工具,直接用SQL语句等等有关系?
你不说俺还明白,越说俺越糊涂。
0 请登录后投票
   发表时间:2005-09-02  
partech 写道
myace 写道

“Extension Object/Extension Interface”的实现不在意是否使用AOP。
我们的目的是能够直接使用向customer.save()方法,但是这有引入
对DAO接口或实现的依赖。在xiecc的“Domain injection”方法中,实际上还是对DAO接口有依赖。最终的方法调用向这样“customer.getDAO().save()”。

drliujia 写道
其实本质上都差不多的,aspectj也就是让代码好看点,把我们不愿意看到的对domain object增强的部分给分离到了aspect里面,编译后的class不还是乱成一团?

如果你们知道UnitOfWork用法的话,就再也不想多看一眼DAO了。

下面的一个草案,虽说现在可以改进的更好,但思想还是可以使用的。
http://forum.iteye.com/viewtopic.php?t=13594


UnitOfWork虽然是个不错的想法,但是OR映射时复杂的,感觉这种简单的方法很难解决全部问题,这点好像Martin Fowler也说了。
况且 new 一个对象并不意味着在数据库中添加一条数据。
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics