分享
 
 
 

跟我学AspectJ(四)

王朝java/jsp·作者佚名  2006-01-08
窄屏简体版  字體: |||超大  

第二章 AspectJ语言

通知(Advice)

通知定义几个方面的实现,以便于在特定的程序运行段执行。这些特定段可以使用命名的切点给出也可以使用匿名切点。下面是一个使用命名切点的通知的例子:

pointcut setter(Point p1, int newval): target(p1) && args(newval)

(call(void setX(int) ||

call(void setY(int)));

before(Point p1, int newval): setter(p1, newval) {

System.out.println("About to set something in " + p1 +

" to the new value " + newval);

}

使用匿名切点也可以实现同样的通知,如下

before(Point p1, int newval): target(p1) && args(newval)

(call(void setX(int)) ||

call(void setY(int))) {

System.out.println("About to set something in " + p1 +

" to the new value " + newval);

}

下面是一些不同的通知

这个before通知在匿名切点捕捉到连接点之前运行

before(Point p, int x): target(p) && args(x) && call(void setX(int)) {

if (!p.assertX(x)) return;

}

这个after通知在匿名切点捕捉各个连接点之后运行,无论程序是正常返回还是抛出异常。

after(Point p, int x): target(p) && args(x) && call(void setX(int)) {

if (!p.assertX(x)) throw new PostConditionViolation();

}

下面的after通知在匿名切点捕捉到连接点后且仅仅在程序正常返回的情况下在运行。

after(Point p) returning(int x): target(p) && call(int getX()) {

System.out.println("Returning int value " + x + " for p = " + p);

}

下面的after通知在匿名切点捕捉到连接点后且程序抛处异常的情况下运行。

after() throwing(Exception e): target(Point) && call(void setX(int)) {

System.out.println(e);

}

around通知可以取代被捕捉的连接点而执行它自己定义的逻辑,程序原有的逻辑可以通过调用一个特定的方法proceed执行。

void around(Point p, int x): target(p)

&& args(x)

&& call(void setX(int)) {

if (p.assertX(x)) proceed(p, x);

p.releaseResources();

}

类型间声明(Inter-type declarations)

方面能够声明属于其他类型的成员(字段、方法和构造子)。这些被称为类型间成员。方面也能够声明实现新接口或扩展一个新类的其他类型。这里有一些这样的声明的例子。

下述声明每个Server对象有一个名为disabled的boolean类型字段,其初始值为false:

private boolean Server.disabled=false;

这里声明了一个私有的字段,只有这个方面能够访问这个字段。就算是Server对象本身有另一个私有字段disabled(在Server内或其他方面里定义)也不会产生名字冲突,因为对于disabled引用没有二义性。

下面代码段声明每个Point对象有一个名为getX的方法,它返回各自x变量的值:

public int Point.getX(){ return this.x;}

在方法内部,this就是当前执行的Point对象。因为方法声明为公共方法,所以任何代码都能调用它,但是如果有另一个Point.getX()声明,那么就会产生编译期的冲突。

下面的公有声明定义Point对象的一个构造函数,它有两个整型参数:

public Point.new(int x,int y){ this.x=x;this.y=y; }

下面是一个公有字段声明:

public int Point.x=0;

它为Point对象声明了一个x公有字段并初始化为0,因为字段是公有的,在任何地方都可以访问它,所以如果还有另一个x字段,则会产生冲突。

下面声明了Point类实现的接口Comparable

declare parents : Point implement Comparable;

当然,除非Point类实现了接口的方法,否则会有错误。

下面则为Point类声明了其扩展的类GeometricObject

declare parents : Point extends GeometricObject;

一个方面可以有多个类型间声明。例如下面的声明。

Public String Point.name;

Public void Point.setName(String name){ this.name=name; }

类型间成员仅仅能够有一个目标类型,但是通常你可能想要在多个类型上声明相同的成员。这可以通过联合使用类型间成员和一个私有接口实现。

aspect A {

private interface HasName {}

declare parents: (Point || Line || Square) implements HasName;

private String HasName.name;

public String HasName.getName() { return name; }

}

这里声明了一个HasName接口,并声明Point、Line或Square都实现这个接口。而且为接口声明了私有字段name和公有方法getName。

类型间变量的作用域

AspectJ允许私有、包保护(缺省)以及公有的类型间声明。私有意味着与aspect有私有关系,而与目标对象无关(即目标对象不知道变量或方法的存在)。因此,如果一个方面作出一个字段的私有类型间声明

Private int Foo.x;

那么方面中的代码可以访问Foo的x字段,其他类或方面都不行。类似地,如果一个方面作出一个包保护类型间声明

int Foo.x;

那么在包中的任何代码都可以访问它,包外的代码无权访问。

举例:PointAssertions

这个例子包括一个类和一个方面。方面为Point声明了私有的assertion方法assertX和assertY。利用这两个断言方法方面对setX和setY方法的调用提供了保护。断言方法声明为私有是因为没有其他地方需要用到它们,只有方面内部可以使用这些方法。

class Point {

int x, y;

public void setX(int x) { this.x = x; }

public void setY(int y) { this.y = y; }

public static void main(String[] args) {

Point p = new Point();

p.setX(3);

p.setY(333);//非法的Y值

}

}

aspect PointAssertions {

//如果X或Y的值不在0到100之间,则视为非法。

private boolean Point.assertX(int x) {

return (x <= 100 && x >= 0);

}

private boolean Point.assertY(int y) {

return (y <= 100 && y >= 0);

}

before(Point p, int x): target(p) && args(x) && call(void setX(int)) {

if (!p.assertX(x)) { //若非法输入X,则输出提示信息

System.out.println("Illegal value for x"); return;

}

}

before(Point p, int y): target(p) && args(y) && call(void setY(int)) {

if (!p.assertY(y)) { //若非法输入Y,则输出提示信息

System.out.println("Illegal value for y"); return;

}

}

}

thisJoinPoint

AspectJ提供了一个特别的引用变量,thisJoinPoint,它包含了当前连接点处的相关信息并可以被通知使用。ThisJoinPoint变量仅仅可以在通知环境中被使用,就象this仅能用于非静态方法和构造函数环境中一样。在通知中,thisJoinPoint是org.aspectj.lang.JoinPoint类型的变量。使用它的一个简单作用是直接输出它。和其他Java对象一样,thisJoinPoint有一个toString()方法简化了格式化的输出:

class TraceNonStaticMethods {

before(Point p): target(p) && call(* *(..)) {

System.out.println("Entering " + thisJoinPoint + " in " + p);

}

}

thisJoinPoint可以被用来访问静态和动态信息,比如说参数等:

thisJoinPoint.getArgs();

另外,它持有一个包括所有静态信息的对象,可以通过以下方法得到该对象的引用:

thisJoinPoint.getStaticPart();

如果你仅需要关于连接点处的静态信息,你可能访问连接点的静态部分直接使用变量thisJoinPointStaticPart。使用它将避免运行时直接使用thisJoinPoint创建连接点对象。

通常情况下

thisJoinPointStaticPart == thisJoinPoint.getStaticPart()

thisJoinPoint.getKind() == thisJoinPointStaticPart.getKind()

thisJoinPoint.getSignature() == thisJoinPointStaticPart.getSignature()

thisJoinPoint.getSourceLocation() == thisJoinPointStaticPart.getSourceLocation()

还有一个相关变量:thisEnclosingJoinPointStaticPart。它与thisJoinPointStaticPart类似,使用它可以打印调用者的位置,例如

before() : execution (* *(..)) {

System.err.println(thisEnclosingJoinPointStaticPart.getSourceLocation())

}

导读

本系列下一章将使用AspectJ实现一些具体的例子,以便读者可以加强对AspectJ的理解并熟悉各种语法。

更多信息

1.AspectJ安装和配置指南

2.跟我学AspectJ(一)

如果需要转贴请写名作者和出处。

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有