AspectJ初探

AspectJ初探

早晨收到IBM developerWorks的邮件,看看有啥值得关注的东东。看到篇关于AOP的介绍,就大致读了一下,文章倒没什么新意,就是介绍AOP在项目中的应用,如何简化log机制等。

我对AOP也有些了解,主要研究过Spring中AOP实现使用的Dynamic Proxy机制,对于pointcut和advice也有些概念。但也仅此而已,没有实际写过一行AOP的代码,更不用说在项目中使用AOP了。点了点文章末尾的链接,进入了AOP的世界,看看AOP的几种不同实现,以及对其的比较文章,倒引起了我对AspectJ的兴趣。并非其它实现如AspectWerkz,JBoss4.0或Spring不如AspectJ,它们各有侧重,但我对AspectJ的静态检查和较好的IDE集成性(有eclipse3.0的插件ajdt)比较好奇。于是网上down了个ajdt(下载url:http://www.eclipse.org/ajdt/),开始了对AspectJ的探索之旅。

Ajdt的安装和其它eclipse插件完全一样,解压,拷贝到相应目录,重启eclipse就OK了。进入eclipse,发现多了个按钮,有AJ字样,点击就弹出创建AspectJ项目的窗口。先别着急,再查看window->preferences发现多了AspectJ和Visualiser栏目,随便点点,也不用做什么更改,就能确认AJDT已经成功的集成进来了。

新建个AspectJ项目,项目名就叫myaspect吧。在Package Explorer 中展开新项目,发现除了jre外它自己加入了一个AspectJ的lib,这就是AspectJ的类库了,下面是一个叫build.ajproperties的文件,肯定是配置文件了,但具体配什么我也没管太多,就希望马上能写段代码看到AOP的威力了,倒就因为这个后面郁闷好久,这是后话!

写点什么代码呢,初次使用,当然是越简单越好,但我对AspectJ的语法一窍不通啊。想到网上搜索,又觉得不系统,而且大部分文章都是讲AspectJ的好处,讲到具体使用却很少。正郁闷时看到eclipse的help菜单,想想说不定有帮助。打开help content,果然多了AspectJ Language GuideAspectJ Development User Guide目录。这其实有点出乎我的意外,eclipse插件我也装了不少,如tomcat,lomboz等,但都没有帮助文档的,看来AJDT就是考虑的周到,这也大大增加了我对AspectJ的好感,得好好研究研究!文档当然都是英文,但这可难不倒俺,当程序员的英文其它水平不行,说到“读”那却肯定没问题的。浏览了下这些help,找了篇Getting Started的Basic tutorial就跟着做了,新建项目,新建个叫Hello的类,代码很少,就是打印“Hello”。

 

1 public   static   void  main(String[] args)  {
2     sayHello();
3}
 
4
5 public   static   void  sayHello()  {
6     System.out.print("Hello");
7}
 

 

然后新建个aspect,叫World吧,代码也很简单,拷贝过去先:

1 public  aspect World 
2     pointcut greeting() : execution(*Hello.sayHello(..)); 
3
4     after() returning() : greeting() 
5         System.out.println(" World!"); 
6     }
 
7
8}

 

AspectJ语法我不懂,但英文还认识,pointcut就是切点的意思,这段代码估计就是在执行Hello.sayHello方法后,打印一个“World!”,但*和..是啥意思我就不大了解了。先急着看效果,我就运行Hello类了,当然我按照文档做,要run as AspectJ/Java application。运行结果:“Hello”。咋不对呢,难道我写错了?先删除代码,这次不拷贝了,自己手写。还真认识pointcut,after这些关键字,会高亮显示,边打边就报错,打全了函数就好了,这跟java的静态检查完全一样嘛。试着删除*,报错,删除..,好像没事,删除returning(),好像也没事,我这纯粹是盲人摸象嘛!呵呵,没办法,我就这性格。倒也增加了几分对了解其语法的渴望。但现在我还不看,第一次运行,连个象样的结果还没出来啊,这不是打击我积极性吗?手工输入了一遍,没错误了,运行。。。靠!还是老样子,这什么Getting Started啊,我心中暗骂。仔细在看看文档,好像也没问题啊,但它说的那个Cross References显示好像和我不一样,看来是我的问题。出师不利啊!

我可没那么容易放弃,再来一遍,反正简单,几分钟又好了,但结果还是一样。我郁闷啊!失意中我瞎点点,打开了那个property文件,还是图形化的呢。诶,好像那个World.aj没勾上,难道因为这个?仔细看看说明,included files…对了,AspectJ的特性就是需要用自己的acj编译器进行编译,这可能就是编译的类列表。勾上,保存文件,果然开始编译,运行。。。结果为:“Hello World!”成功了,哈哈,这可是俺的第一个AOP成功案例啊!兴奋中想起AspectJ要用自己的编译器编译,编译出来是.class文件,但肯定往里面加了些东西。于是到eclipse的workspace中找编译出来的class文件,双击打开(嘿嘿!俺有小颖,自动反编译),这就是经AspectJ编译后的Hello类代码,原来加了行语句。

1      public   static   void  sayHello()
2
3      {        System.out.print("Hello");       
                   World.aspectOf().ajc$afterReturning$helloworld_World$
1$f69f5afa();
4
5         }

6

World.aj也编译成了World.class,代码较长:

 1 package helloworld;
 2
 3 import java.io.PrintStream;
 4
 5 import org.aspectj.lang.NoAspectBoundException;
 6
 7 public   class  World
 8
 9 {
10
11    private static Throwable ajc$initFailureCause;
12
13    public static final World ajc$perSingletonInstance;
14
15    public World()
16
17    {
18
19    }

20
21    public void ajc$afterReturning$helloworld_World$1$f69f5afa()
22
23    {
24
25        System.out.println("World!");
26
27    }

28
29    public static World aspectOf()
30
31    {
32
33        if(ajc$perSingletonInstance == null)
34
35            throw new NoAspectBoundException("helloworld_World", ajc$initFailureCause);
36
37        else
38
39            return ajc$perSingletonInstance;
40
41    }

42
43    public static boolean hasAspect()
44
45    {
46
47        return ajc$perSingletonInstance != null;
48
49    }

50
51    private static void ajc$postClinit()
52
53    {
54
55        ajc$perSingletonInstance = new World();
56
57    }

58
59    static 
60
61    {
62
63        try
64
65        {
66
67            ajc$postClinit();
68
69        }

70
71        catch(Throwable throwable)
72
73        {
74
75            ajc$initFailureCause = throwable;
76
77        }

78
79    }

80
81}

82

研究一下:也就是生成个默认构造函数的World类,加了个ajc$afterReturning$helloworld_World$1$f69f5afa()方法,其它好像都是AspectJ生成的class必带的代码,定义了一个public static final World ajc$perSingletonInstance的类,还有一个private static Throwable ajc$initFailureCause异常,public static World aspectOf()和public static boolean hasAspect()会被自动调用。这就是AspectJ能运行的原理了,当然还有更复杂的东西,但从这个最简单的例子也能了解些端倪了。

接下来就是学习它的语法了,其实也不难(我就奇怪网上把AspectJ的学习曲线说的多陡峭,比java难多少),也就是pointcut和advice,各自有各自的一些关键字。我也对开始瞎试,有的报错,有的不报错的原因有了理论的认识了。

整个探索的时间也不长,1个小时左右,比我写这篇东西少多了,呵呵!打字打的累啊,回去打星际去!看哪天有空,接着研究,也一定写篇文章,估计也还有人看的,呵呵!

你可能感兴趣的:(AspectJ初探)