论坛首页 Java企业应用论坛

关于aop的几个细节问题

浏览 6843 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2004-08-12  
1。如果有一个class/interface C, 两个独立的aspect A1, A2 (各自加入一些副作用)。
如果最终两个aspect都被织入,那么这两个aspect谁先起作用?是否有明确的定义?(比如在weaving的时候可以指定顺序)

2。aspect的编织是否重入?比如,我对class C的方法f织入新东西,
那么当我调用new C().f();的时候,这个新东西起作用。没问题。

但是假如C的g()函数内部调用了f()呢?这个新东西是否也影响原来的这个调用?

如果影响的话,那么dynamic proxy就不可能代替aop。也就是说aop确实有独特的功能。
   发表时间:2004-08-12  
ajoo 写道
如果最终两个aspect都被织入,那么这两个aspect谁先起作用?是否有明确的定义?(比如在weaving的时候可以指定顺序)

可以的, 如果现在哪个AOP框架不能这样做的话, 还敢出来混?

ajoo 写道
但是假如C的g()函数内部调用了f()呢?这个新东西是否也影响原来的这个调用?

可以的, 组合pointcut: call(void f()) && withincode(void g()) ??

然则偶恰恰对于这2点有一些置疑, 可惜要上班了 , 晚上回家再写些代码举例唐僧唐僧
0 请登录后投票
   发表时间: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呢, 给偶扫扫盲吧......
0 请登录后投票
   发表时间:2004-08-13  
Readonly 写道
ajoo 写道
但是假如C的g()函数内部调用了f()呢?这个新东西是否也影响原来的这个调用?

可以的, 组合pointcut: call(void f()) && withincode(void g()) ??


偶现在的疑问是, OOP教育偶要封装以保持对外行为的一致
那么, 现在偶封装好了f(), 但是AOP说, 可以让你在withincode g()和 withoutcode g()的时候, 有不同的行为, 这是什么鬼目的?? 对于OOP的升级还是破坏? 实际用途是干什么? 偶小小的脑袋又开始迷糊了......
0 请登录后投票
   发表时间:2004-08-13  
所谓"副作用",有直接影响业务逻辑的,也有在业务逻辑无法感知的地方产生副作用的.
比如:直接在log里打印一个trace信息.
那么如果两个aspect都打印trace信息,必须要有个规定谁先谁后啊.
0 请登录后投票
   发表时间: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的调用,只能由系统来调用。
0 请登录后投票
   发表时间:2004-08-14  
那不乱套了?函数式不一样,没有副作用,谁先谁后没什么意义。aspect如果不能精确定义顺序,我只能说这东西就是扯淡
0 请登录后投票
   发表时间: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应用面前止步不前.
0 请登录后投票
   发表时间:2004-08-15  
不管横向还是纵向。从语义上说,只要这两个东西采取不同的顺序造成的结果可能对我有所影响,顺序就应该精确定义。

这不是方法论相关的,而是底层的语义学相关的。我们不能容忍模棱两可。或者打印出"hello world",或者打印"world hello"。但是别告诉我:它可能打印"hello world", 也可能打印"world hello"。

函数式编程里面,没有副作用,所以哪个声明先发生对程序结果没有任何影响。但是,看一下haskell的monad,在发生顺序对结果有影响的时候,即使是函数式编程也要精确定义顺序。
0 请登录后投票
   发表时间: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");;
	}
}
0 请登录后投票
论坛首页 Java企业应用版

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