浏览 6843 次
锁定老帖子 主题:关于aop的几个细节问题
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2004-08-12
如果最终两个aspect都被织入,那么这两个aspect谁先起作用?是否有明确的定义?(比如在weaving的时候可以指定顺序) 2。aspect的编织是否重入?比如,我对class C的方法f织入新东西, 那么当我调用new C().f();的时候,这个新东西起作用。没问题。 但是假如C的g()函数内部调用了f()呢?这个新东西是否也影响原来的这个调用? 如果影响的话,那么dynamic proxy就不可能代替aop。也就是说aop确实有独特的功能。 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间:2004-08-12
ajoo 写道 如果最终两个aspect都被织入,那么这两个aspect谁先起作用?是否有明确的定义?(比如在weaving的时候可以指定顺序)
可以的, 如果现在哪个AOP框架不能这样做的话, 还敢出来混? ajoo 写道 但是假如C的g()函数内部调用了f()呢?这个新东西是否也影响原来的这个调用?
可以的, 组合pointcut: call(void f()) && withincode(void g()) ?? 然则偶恰恰对于这2点有一些置疑, 可惜要上班了 , 晚上回家再写些代码举例唐僧唐僧 |
|
返回顶楼 | |
发表时间:2004-08-13
ajoo 写道 1。如果有一个class/interface C, 两个独立的aspect A1, A2 (各自加入一些副作用)。
如果存在side effect的话, aspect就需要考虑在其之前,或者在其之后织入的aspect了, 那么按照AOP的规范, 这样的代码是写不出来的, 因为你是很难知道已经织入的aspect到底有什么side effect, 而更不用说未织入的aspect了. 这就是为什么偶们看到拦截器性质的aspect之间都是正交的, 只有用来做事务, 日志这种中间件的功能, 而不能用来做业务逻辑的AOP原因么?? AOPer, 如果只是拦截器, 如果只是mixin, 那么偶小小脑袋真的无法理解为什么非要叫XOP呢, 给偶扫扫盲吧...... |
|
返回顶楼 | |
发表时间:2004-08-13
Readonly 写道 ajoo 写道 但是假如C的g()函数内部调用了f()呢?这个新东西是否也影响原来的这个调用?
可以的, 组合pointcut: call(void f()) && withincode(void g()) ?? 偶现在的疑问是, OOP教育偶要封装以保持对外行为的一致 那么, 现在偶封装好了f(), 但是AOP说, 可以让你在withincode g()和 withoutcode g()的时候, 有不同的行为, 这是什么鬼目的?? 对于OOP的升级还是破坏? 实际用途是干什么? 偶小小的脑袋又开始迷糊了...... |
|
返回顶楼 | |
发表时间:2004-08-13
所谓"副作用",有直接影响业务逻辑的,也有在业务逻辑无法感知的地方产生副作用的.
比如:直接在log里打印一个trace信息. 那么如果两个aspect都打印trace信息,必须要有个规定谁先谁后啊. |
|
返回顶楼 | |
发表时间:2004-08-14
Readonly 写道 Readonly 写道 ajoo 写道 但是假如C的g()函数内部调用了f()呢?这个新东西是否也影响原来的这个调用?
可以的, 组合pointcut: call(void f()) && withincode(void g()) ?? 偶现在的疑问是, OOP教育偶要封装以保持对外行为的一致 那么, 现在偶封装好了f(), 但是AOP说, 可以让你在withincode g()和 withoutcode g()的时候, 有不同的行为, 这是什么鬼目的?? 对于OOP的升级还是破坏? 实际用途是干什么? 偶小小的脑袋又开始迷糊了...... within的功能主要在于更好地定义pointcut的作用范围,过滤掉一些范围。 比如,call f1() && within main() 表示只有在main()代码范围内, 对f1()的调用才会被截获。 ajoo 写道 所谓"副作用",有直接影响业务逻辑的,也有在业务逻辑无法感知的地方产生副作用的.
比如:直接在log里打印一个trace信息. 那么如果两个aspect都打印trace信息,必须要有个规定谁先谁后啊. good point. Aspect的调用顺序问题是存在的。只能依靠系统先碰到哪个pointcut。 对于相同pointcut的不同Aspect,我也不知道如何显式地定义Aspect的顺序。 Aspect有些类似于函数式编程 的函数入口点。程序无法直接控制Aspect的调用,只能由系统来调用。 |
|
返回顶楼 | |
发表时间:2004-08-14
那不乱套了?函数式不一样,没有副作用,谁先谁后没什么意义。aspect如果不能精确定义顺序,我只能说这东西就是扯淡
|
|
返回顶楼 | |
发表时间:2004-08-14
ajoo 写道 那不乱套了?函数式不一样,没有副作用,谁先谁后没什么意义。aspect如果不能精确定义顺序,我只能说这东西就是扯淡
AOP思路的飞跃其实就在就在这里。Aspect关心的是横向,不是纵向。Aspect不关心顺序,只关心匹配。 我们接受OOP很自然,因为OOP是建立在过程基础上的,符合写应用系统的习惯。我们不能按照过程编程的思路套AOP。AOP介乎过程编程和函数式编程之间,但更接近于函数式编程。 比如,在XSL中,你如果写出两个同样的匹配模式入口,或者两个匹配模式入口有交集,会发生什么事情? 歧义肯定会发生,系统自己会有一套解决这个歧义的做法。虽然有这样的副作用,但XSL还是有自己的用处。 AOP的pointcut也一样。当几个Advice同时作用于同一个pointcut的时候,这种歧义就会发生。 CacheAspect { advice(); : pointcut_a; } TransactionAspect { advice(); : pointcut_a; } 这种情况下,一般来说,哪个aspect先定义,就会被先调用。不同的AOP实现,当然都有自己的精确地定义顺序的方法。但程序员无法直接干预这个顺序定义。 实际情况更复杂,不同的pointcut范围之间,还有交集。 对于这一点,我的建议是,尽量以pointcut为中心,避免定义重叠的pointcut。 每个pointcut只对应一个aspect advice, 尽量避免歧义。 必要的时候,把advice里面的功能声明为公用Class, 便于组装复合的aspect advice. 我也很头疼这个问题,正在思考探索中. 正是诸多的代价令我这个被AOP思想折服的AOPer,在AOP应用面前止步不前. |
|
返回顶楼 | |
发表时间:2004-08-15
不管横向还是纵向。从语义上说,只要这两个东西采取不同的顺序造成的结果可能对我有所影响,顺序就应该精确定义。
这不是方法论相关的,而是底层的语义学相关的。我们不能容忍模棱两可。或者打印出"hello world",或者打印"world hello"。但是别告诉我:它可能打印"hello world", 也可能打印"world hello"。 函数式编程里面,没有副作用,所以哪个声明先发生对程序结果没有任何影响。但是,看一下haskell的monad,在发生顺序对结果有影响的时候,即使是函数式编程也要精确定义顺序。 |
|
返回顶楼 | |
发表时间:2004-08-17
ajoo 写道 2。aspect的编织是否重入?比如,我对class C的方法f织入新东西, 那么当我调用new C().f();的时候,这个新东西起作用。没问题。 但是假如C的g()函数内部调用了f()呢?这个新东西是否也影响原来的这个调用? 如果影响的话,那么dynamic proxy就不可能代替aop。也就是说aop确实有独特的功能。 无论是直接调用,还是在其它方法体内调用,一旦调用f()方法,都有效。 ajoo 写道 那不乱套了?函数式不一样,没有副作用,谁先谁后没什么意义。aspect如果不能精确定义顺序,我只能说这东西就是扯淡 aspect是可以定义顺序的,语法如下: declare precedence : TypePattern1, TypePattern2, ..; 在aspect直接调用java类中的private field,可以使用关键字:privileged。 GirlTest.java public class GirlTest extends TestCase { private Girl girl = null; protected void setUp(); { girl = new Girl();; } public void testMultiAspect(); { girl.laugh();; girl.cry();; } public void testLove(); { girl.love();; } } Girl.java public class Girl { private String feature = "Pretty"; public void laugh(); { System.out.println("HeHe");; } public void cry(); { System.out.println("......");; } public void love(); { System.out.println("Loving");; cry();; laugh();; } } GirlHeartAspect.aj privileged public aspect GirlHeartAspect { declare precedence: GirlHeartAspect, GirlFigAspect; before(Girl girl); : call(void Girl.laugh();); && target(girl); { System.out.println("Joy "+ girl.feature);; } after(); : call(void Girl.cry();); { System.out.println("Sorrow");; } } GirlFigAspect.aj public aspect GirlFigAspect { before(); : call(void Girl.laugh();); { System.out.println("beautiful");; } after(); : call(void Girl.cry();); { System.out.println("uglily");; } } |
|
返回顶楼 | |