在前面《[AspectJ] 明明白白AspectJ (1) 》中用例子说明了AspectJ的确是代码生成器。
现在,同样的方式,将官方提供的例子“Bean Example”(File -->New -->Project -->AspectJ -->AspectJ Examples --> Bean Example)简单剖析一下。Bean Example主要是利用AOP来实现属性改变通知,效果像观察者模式来关注bean的属性,但它是用java.beans.PropertyChangeSupport来实现的。如果你对java.beans.PropertyChangeSupport用法不了解,可以参考我以前的一篇随笔《[java 拾遗篇] JavaBean实现约束属性简单例 》。
Bean Example的源码有三个文件,分别是Point.java , BoundPoint.aj , Demo.java
Point.java
package bean;


class Point
{

protected int x = 0;
protected int y = 0;


/** *//**
* Return the X coordinate
*/

public int getX()
{
return x;
}


/** *//**
* Return the y coordinate
*/

public int getY()
{
return y;
}


/** *//**
* Set the x and y coordinates
*/

public void setRectangular(int newX, int newY)
{
setX(newX);
setY(newY);
}


/** *//**
* Set the X coordinate
*/

public void setX(int newX)
{
x = newX;
}


/** *//**
* set the y coordinate
*/

public void setY(int newY)
{
y = newY;
}


/** *//**
* Move the point by the specified x and y offset
*/

public void offset(int deltaX, int deltaY)
{
setRectangular(x + deltaX, y + deltaY);
}


/** *//**
* Make a string of this
*/

public String toString()
{
return "(" + getX() + ", " + getY() + ")" ;
}
}
BoundPoint.aj
package bean;

import java.beans.*;
import java.io.Serializable;


/**//*
* Add bound properties and serialization to point objects
*/


aspect BoundPoint
{

/**//*
* privately introduce a field into Point to hold the property
* change support object. `this' is a reference to a Point object.
*/
private PropertyChangeSupport Point.support = new PropertyChangeSupport(this);


/**//*
* Introduce the property change registration methods into Point.
* also introduce implementation of the Serializable interface.
*/

public void Point.addPropertyChangeListener(PropertyChangeListener listener)
{
support.addPropertyChangeListener(listener);
}

public void Point.addPropertyChangeListener(String propertyName,

PropertyChangeListener listener)
{

support.addPropertyChangeListener(propertyName, listener);
}

public void Point.removePropertyChangeListener(String propertyName,

PropertyChangeListener listener)
{
support.removePropertyChangeListener(propertyName, listener);
}


public void Point.removePropertyChangeListener(PropertyChangeListener listener)
{
support.removePropertyChangeListener(listener);
}


public void Point.hasListeners(String propertyName)
{
support.hasListeners(propertyName);
}

declare parents: Point implements Serializable;


/** *//**
* Pointcut describing the set<property> methods on Point.
* (uses a wildcard in the method name)
*/
pointcut setter(Point p): call(void Point.set*(*)) && target(p);


/** *//**
* Advice to get the property change event fired when the
* setters are called. It's around advice because you need
* the old value of the property.
*/

void around(Point p): setter(p)
{
String propertyName =
thisJoinPointStaticPart.getSignature().getName().substring("set".length());
int oldX = p.getX();
int oldY = p.getY();
proceed(p);

if (propertyName.equals("X"))
{
firePropertyChange(p, propertyName, oldX, p.getX());

} else
{
firePropertyChange(p, propertyName, oldY, p.getY());
}
}


/**//*
* Utility to fire the property change event.
*/
void firePropertyChange(Point p,
String property,
double oldval,

double newval)
{
p.support.firePropertyChange(property,
new Double(oldval),
new Double(newval));
}
}
Demo.java
package bean;

import java.beans.*;
import java.io.*;


public class Demo implements PropertyChangeListener
{

static final String fileName = "test.tmp";


/** *//**
* when Demo is playing the listener role,
* this method reports that a propery has changed
*/

public void propertyChange(PropertyChangeEvent e)
{
System.out.println("Property " + e.getPropertyName() + " changed from " +
e.getOldValue() + " to " + e.getNewValue() );
}


/** *//**
* main: test the program
*/

public static void main(String[] args)
{
Point p1 = new Point();
p1.addPropertyChangeListener(new Demo());
System.out.println("p1 =" + p1);
p1.setRectangular(5,2);
System.out.println("p1 =" + p1);
p1.setX( 6 );
p1.setY( 3 );
System.out.println("p1 =" + p1);
p1.offset(6,4);
System.out.println("p1 =" + p1);
save(p1, fileName);
Point p2 = (Point) restore(fileName);
System.out.println("Had: " + p1);
System.out.println("Got: " + p2);
}


/** *//**
* Save a serializable object to a file
*/

static void save(Serializable p, String fn)
{

try
{
System.out.println("Writing to file: " + p);
FileOutputStream fo = new FileOutputStream(fn);
ObjectOutputStream so = new ObjectOutputStream(fo);
so.writeObject(p);
so.flush();

} catch (Exception e)
{
System.out.println(e);
System.exit(1);
}
}


/** *//**
* Restore a serializable object from the file
*/

static Object restore(String fn)
{

try
{
Object result;
System.out.println("Reading from file: " + fn);
FileInputStream fi = new FileInputStream(fn);
ObjectInputStream si = new ObjectInputStream(fi);
return si.readObject();

} catch (Exception e)
{
System.out.println(e);
System.exit(1);
}
return null;
}
}
跑跑Demo输出的结果:
p1 =(0, 0)
Property X changed from 0.0 to 5.0
Property Y changed from 0.0 to 2.0
p1 =(5, 2)
Property X changed from 5.0 to 6.0
Property Y changed from 2.0 to 3.0
p1 =(6, 3)
Property X changed from 6.0 to 12.0
Property Y changed from 3.0 to 7.0
p1 =(12, 7)
Writing to file: (12, 7)
Reading from file: test.tmp
Had: (12, 7)
Got: (12, 7)

好,跟上次一样,将编译的代码反编来对照一下。看看AspectJ根据“规则”(aspect的定义)修改了代码的哪些地方,给你一个明白!
三个文件:Point.class , BoundPoint.class , Demo.class
代码上,我添加了一些注释,反编译出来的文件般都没什么注释的。
Point.class
package bean;

import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.io.Serializable;
import org.aspectj.lang.Signature;
import org.aspectj.runtime.internal.AroundClosure;
import org.aspectj.runtime.reflect.Factory;

//BoundPoint.aj 中的声明“declare parents: Point implements Serializable;”使Point实现了Serializable
public class Point implements Serializable


{

Point()

{
//为Point添加向关注者提供属性改变通知的支持,target为this(自身)
BoundPoint.ajc$interFieldInit$bean_BoundPoint$bean_Point$support(this);
x = 0;
y = 0;
}

public int getX()

{
return x;
}

public int getY()

{
return y;
}

public void setRectangular(int newX, int newY)

{
int i = newX;
Point point = this;
//原来的setX(newX)函数被定义为pointcut了,在aspectj是代码生成器,这里就难免不作变动咯,呵呵,setX(newX)前后的通知
//但是有点奇怪,同下面定义的setX_aroundBody1$advice方法签名不一致哦,有待研究
setX_aroundBody1$advice(this, point, i, BoundPoint.aspectOf(), point, null, ajc$tjp_0);
int j = newY;
Point point1 = this;
//setY(newY)前后的通知
setY_aroundBody3$advice(this, point1, j, BoundPoint.aspectOf(), point1, null, ajc$tjp_1);
}

public void setX(int newX)

{
x = newX;
}

public void setY(int newY)

{
y = newY;
}

public void offset(int deltaX, int deltaY)

{
setRectangular(x + deltaX, y + deltaY);
}

public String toString()

{
return (new StringBuilder("(")).append(getX()).append(", ").append(getY()).append(")").toString();
}


/** *//**
* 改变属性(x)值
* @param point
* @param point1
* @param i
*/
private static final void setX_aroundBody0(Point point, Point point1, int i)

{
point1.setX(i);
}


/** *//**
* 调用setX(newX)前后的通知,想一想,因为Point实现属性改变通知支持,那么当改变属性(用setter函数),用aop实现的,
* 那么setX(newX)的代码就会被修改。属性还是要改便的呀,所以“setX_aroundBody0(this, s1, ajc_aroundClosure);”的作用
* 就是改变属性值的。在改变属性通知需要不仅要包含新值,同时也要包含旧值,所有在“setX_aroundBody0(this, s1, ajc_aroundClosure);”
* 之前还是要用变量保存一下旧值,在属性改变之后,即调用“setX_aroundBody0(this, s1, ajc_aroundClosure);”之后,就发起通知
*/
private static final void setX_aroundBody1$advice(BoundPoint this, Point p, AroundClosure ajc_aroundClosure, org.aspectj.lang.JoinPoint.StaticPart thisJoinPointStaticPart, String propertyName, int oldX, int oldY)

{
String s = oldY.getSignature().getName().substring("set".length());
//这里有点奇怪吧
int i = propertyName.getX();
int j = propertyName.getY();
int k = oldX;
String s1 = propertyName;
setX_aroundBody0(this, s1, ajc_aroundClosure);
if(s.equals("X"))
BoundPoint.ajc$inlineAccessMethod$bean_BoundPoint$bean_BoundPoint$firePropertyChange(thisJoinPointStaticPart, propertyName, s, i, propertyName.getX());
else
BoundPoint.ajc$inlineAccessMethod$bean_BoundPoint$bean_BoundPoint$firePropertyChange(thisJoinPointStaticPart, propertyName, s, j, propertyName.getY());
}

private static final void setY_aroundBody2(Point point, Point point1, int i)

{
point1.setY(i);
}


/** *//**
* 调用setY(int newY)前后的通知
*/
private static final void setY_aroundBody3$advice(BoundPoint this, Point p, AroundClosure ajc_aroundClosure, org.aspectj.lang.JoinPoint.StaticPart thisJoinPointStaticPart, String propertyName, int oldX, int oldY)

{
String s = oldY.getSignature().getName().substring("set".length());
int i = propertyName.getX();
int j = propertyName.getY();
int k = oldX;
String s1 = propertyName;
setY_aroundBody2(this, s1, ajc_aroundClosure);
if(s.equals("X"))
BoundPoint.ajc$inlineAccessMethod$bean_BoundPoint$bean_BoundPoint$firePropertyChange(thisJoinPointStaticPart, propertyName, s, i, propertyName.getX());
else
BoundPoint.ajc$inlineAccessMethod$bean_BoundPoint$bean_BoundPoint$firePropertyChange(thisJoinPointStaticPart, propertyName, s, j, propertyName.getY());
}

/** *//**
* 注册监听器,通过BoundPoint来实现,因为是AOP嘛(不要忘了BoundPoint在源码是被定义为aspect的),aspectj作为代码生成器起作用的哦,下面的同样
* @param propertychangelistener
*/
public void addPropertyChangeListener(PropertyChangeListener propertychangelistener)

{
BoundPoint.ajc$interMethod$bean_BoundPoint$bean_Point$addPropertyChangeListener(this, propertychangelistener);
}

public void addPropertyChangeListener(String s, PropertyChangeListener propertychangelistener)

{
BoundPoint.ajc$interMethod$bean_BoundPoint$bean_Point$addPropertyChangeListener(this, s, propertychangelistener);
}

public void hasListeners(String s)

{
BoundPoint.ajc$interMethod$bean_BoundPoint$bean_Point$hasListeners(this, s);
}

public void removePropertyChangeListener(PropertyChangeListener propertychangelistener)

{
BoundPoint.ajc$interMethod$bean_BoundPoint$bean_Point$removePropertyChangeListener(this, propertychangelistener);
}

public void removePropertyChangeListener(String s, PropertyChangeListener propertychangelistener)

{
BoundPoint.ajc$interMethod$bean_BoundPoint$bean_Point$removePropertyChangeListener(this, s, propertychangelistener);
}

protected int x;
protected int y;

/** *//**
* 这个是根据aspect BoundPoint 定义的规则添加的
*/
public PropertyChangeSupport ajc$interField$bean_BoundPoint$support;

/** *//**
* StaticPart是什么也不管了,反正它是包含join point静态信息的对象,看看static初始化块,再对照BoundPoint.aj 的 around(Point p)通知定义就可以意会了吧
*/

private static final org.aspectj.lang.JoinPoint.StaticPart ajc$tjp_0; /**//* synthetic field */

private static final org.aspectj.lang.JoinPoint.StaticPart ajc$tjp_1; /**//* synthetic field */


/** *//**
* static初始化块,主要是获取join point静态信息
*/
static

{
Factory factory = new Factory("Point.java", Class.forName("bean.Point"));
ajc$tjp_0 = factory.makeSJP("method-call", factory.makeMethodSig("1", "setX", "bean.Point", "int:", "newX:", "", "void"), 38);
ajc$tjp_1 = factory.makeSJP("method-call", factory.makeMethodSig("1", "setY", "bean.Point", "int:", "newY:", "", "void"), 39);
}
}
Bean Example.class
package bean;

import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import org.aspectj.lang.NoAspectBoundException;
import org.aspectj.lang.Signature;
import org.aspectj.runtime.internal.AroundClosure;
import org.aspectj.runtime.internal.Conversions;


/** *//**
* 想象一下这个类启动什么作用了?充当的是什么角色?很明显,它控制者Point实例的一举一动(当然是在point cut地方),角色不是很像一个(Point的)幕后策划者?
* 如果说角色像代理了呢?但是没有找到平常代理的实现的影子哦。至少就没有共同的接口。希望大侠们能发表下见解
*
*/
public class BoundPoint


{

BoundPoint()

{
}


/** *//**
* 为Point添加向关注者提供属性改变通知的支持
* @param ajc$this_
*/
public static void ajc$interFieldInit$bean_BoundPoint$bean_Point$support(Point ajc$this_)

{
//在这里,构造了一个被监听对象为Point对象的属性改变通知支持对象,发生什么事,看看下一层的函数
ajc$interFieldSetDispatch$bean_BoundPoint$bean_Point$support(ajc$this_, new PropertyChangeSupport(ajc$this_));
}


/** *//**
* 获取属性改变支持对象。
* 很明显,这里的作用相当于一个getter函数,只是返回的对象是从参数对象(point)中取
* @param point
* @return
*/
public static PropertyChangeSupport ajc$interFieldGetDispatch$bean_BoundPoint$bean_Point$support(Point point)

{
return point.ajc$interField$bean_BoundPoint$support;
}

/** *//**
* 将属性改变通知支持对象注入到指定对象(Point的实例)
* Point本来没有定义ajc$interField$bean_BoundPoint$support的,是AspectJ设定了规则,在编译的时候加入的
* @param point
* @param propertychangesupport
*/
public static void ajc$interFieldSetDispatch$bean_BoundPoint$bean_Point$support(Point point, PropertyChangeSupport propertychangesupport)

{
point.ajc$interField$bean_BoundPoint$support = propertychangesupport;
}

/** *//**
* 监听器注册。
* @param ajc$this_
* @param listener
*/
public static void ajc$interMethod$bean_BoundPoint$bean_Point$addPropertyChangeListener(Point ajc$this_, PropertyChangeListener listener)

{
//由下一层调用的函数可知,这里是向Point ajc$this_注册,并不是this哦
ajc$interFieldGetDispatch$bean_BoundPoint$bean_Point$support(ajc$this_).addPropertyChangeListener(listener);
}

/** *//**
* 监听器注册。
* @param point
* @param propertychangelistener
*/
public static void ajc$interMethodDispatch1$bean_BoundPoint$bean_Point$addPropertyChangeListener(Point point, PropertyChangeListener propertychangelistener)

{
point.addPropertyChangeListener(propertychangelistener);
}

/** *//**
* 监听器注册。
* @param ajc$this_
* @param propertyName
* @param listener
*/
public static void ajc$interMethod$bean_BoundPoint$bean_Point$addPropertyChangeListener(Point ajc$this_, String propertyName, PropertyChangeListener listener)

{
ajc$interFieldGetDispatch$bean_BoundPoint$bean_Point$support(ajc$this_).addPropertyChangeListener(propertyName, listener);
}


/** *//**
* 监听器注册。
* @param point
* @param s
* @param propertychangelistener
*/
public static void ajc$interMethodDispatch1$bean_BoundPoint$bean_Point$addPropertyChangeListener(Point point, String s, PropertyChangeListener propertychangelistener)

{
point.addPropertyChangeListener(s, propertychangelistener);
}


/** *//**
* 监听器移除
* @param ajc$this_
* @param propertyName
* @param listener
*/
public static void ajc$interMethod$bean_BoundPoint$bean_Point$removePropertyChangeListener(Point ajc$this_, String propertyName, PropertyChangeListener listener)

{
ajc$interFieldGetDispatch$bean_BoundPoint$bean_Point$support(ajc$this_).removePropertyChangeListener(propertyName, listener);
}

/** *//**
* 监听器移除
* @param point
* @param s
* @param propertychangelistener
*/
public static void ajc$interMethodDispatch1$bean_BoundPoint$bean_Point$removePropertyChangeListener(Point point, String s, PropertyChangeListener propertychangelistener)

{
point.removePropertyChangeListener(s, propertychangelistener);
}

/** *//**
* 监听器移除
* @param ajc$this_
* @param listener
*/
public static void ajc$interMethod$bean_BoundPoint$bean_Point$removePropertyChangeListener(Point ajc$this_, PropertyChangeListener listener)

{
ajc$interFieldGetDispatch$bean_BoundPoint$bean_Point$support(ajc$this_).removePropertyChangeListener(listener);
}

/** *//**
* 监听器移除
* @param point
* @param propertychangelistener
*/
public static void ajc$interMethodDispatch1$bean_BoundPoint$bean_Point$removePropertyChangeListener(Point point, PropertyChangeListener propertychangelistener)

{
point.removePropertyChangeListener(propertychangelistener);
}

/** *//**
* 判断是否有注册的监听者(返回值为void哦)
* @param ajc$this_
* @param propertyName
*/
public static void ajc$interMethod$bean_BoundPoint$bean_Point$hasListeners(Point ajc$this_, String propertyName)

{
ajc$interFieldGetDispatch$bean_BoundPoint$bean_Point$support(ajc$this_).hasListeners(propertyName);
}


/** *//**
* 判断是否有注册的监听者(返回值为void哦)
* @param point
* @param s
*/
public static void ajc$interMethodDispatch1$bean_BoundPoint$bean_Point$hasListeners(Point point, String s)

{
point.hasListeners(s);
}

void ajc$declare_parents_1()

{
}

void ajc$pointcut$$setter$817(Point point)

{
}


/** *//**
* 这一段不正是BoundPoint.aj定义的Advice分转译么,呵呵。
* @param p
* @param ajc_aroundClosure
* @param thisJoinPointStaticPart
*/
public void ajc$around$bean_BoundPoint$1$5a9d4f02(Point p, AroundClosure ajc_aroundClosure, org.aspectj.lang.JoinPoint.StaticPart thisJoinPointStaticPart)

{
String propertyName = thisJoinPointStaticPart.getSignature().getName().substring("set".length());
int oldX = p.getX();
int oldY = p.getY();
//proceed(p)转译
ajc$around$bean_BoundPoint$1$5a9d4f02proceed(p, ajc_aroundClosure);
//激发属性改变通知
if(propertyName.equals("X"))
ajc$inlineAccessMethod$bean_BoundPoint$bean_BoundPoint$firePropertyChange(this, p, propertyName, oldX, p.getX());
else
ajc$inlineAccessMethod$bean_BoundPoint$bean_BoundPoint$firePropertyChange(this, p, propertyName, oldY, p.getY());
}


/** *//**
* proceed(p)转译,为什么译成这个样子?先不管了
*/
static void ajc$around$bean_BoundPoint$1$5a9d4f02proceed(BoundPoint this, AroundClosure aroundclosure)
throws Throwable

{

Conversions.voidValue(aroundclosure.run(new Object[]
{
this
}));
}

/** *//**
* 激发属性改变通知
* @param p
* @param property
* @param oldval
* @param newval
*/
void firePropertyChange(Point p, String property, double oldval, double newval)

{
ajc$interFieldGetDispatch$bean_BoundPoint$bean_Point$support(p).firePropertyChange(property, new Double(oldval), new Double(newval));
}

/** *//**
* 这个函数相当于构造函数哦,呵呵。返回一个BoundPoint实例
* @return
*/
public static BoundPoint aspectOf()

{
if(ajc$perSingletonInstance == null)
throw new NoAspectBoundException("bean_BoundPoint", ajc$initFailureCause);
else
return ajc$perSingletonInstance;
}


/** *//**
* 是否存在切面
* @return
*/
public static boolean hasAspect()

{
return ajc$perSingletonInstance != null;
}


/** *//**
* ajc$perSingletonInstance 获取BoundPoint实例,算是初始化的一个步骤吧
*/
private static void ajc$postClinit()

{
ajc$perSingletonInstance = new BoundPoint();
}

/** *//**
* 激发属性改变通知
* @param boundpoint
* @param point
* @param s
* @param d
* @param d1
*/
public static void ajc$inlineAccessMethod$bean_BoundPoint$bean_BoundPoint$firePropertyChange(BoundPoint boundpoint, Point point, String s, double d, double d1)

{
boundpoint.firePropertyChange(point, s, d, d1);
}

private static Throwable ajc$initFailureCause;
public static final BoundPoint ajc$perSingletonInstance;

static

{
try

{
ajc$postClinit();//初始化的ajc$perSingletonInstance
}
catch(Throwable throwable)

{
ajc$initFailureCause = throwable;
}
}
}

Demo.class
package bean;

import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;

import org.aspectj.runtime.reflect.Factory;

public class Demo
implements PropertyChangeListener


{

public Demo()


{
}

public void propertyChange(PropertyChangeEvent e)


{
//呵呵,看来aspectj不仅仅是代码生成器,还能做代码优化哦(“+”连接的字符串形式改成StringBuilder了哦)。还是javac本来就拥有的能力?
System.out.println((new StringBuilder("Property ")).append(e.getPropertyName()).append(" changed from ").append(e.getOldValue()).append(" to ").append(e.getNewValue()).toString());
}

public static void main(String args[])


{
Point p1 = new Point();
//注册监听器
BoundPoint.ajc$interMethodDispatch1$bean_BoundPoint$bean_Point$addPropertyChangeListener(p1, new Demo());
System.out.println((new StringBuilder("p1 =")).append(p1).toString());
p1.setRectangular(5, 2);
System.out.println((new StringBuilder("p1 =")).append(p1).toString());
byte byte0 = 6;
Point point = p1;
//p1.setX( 6 );被更换咯
setX_aroundBody1$advice(point, byte0, BoundPoint.aspectOf(), point, null, ajc$tjp_0);
byte byte1 = 3;
Point point1 = p1;
//p1.setY( 3 );被更换咯
setY_aroundBody3$advice(point1, byte1, BoundPoint.aspectOf(), point1, null, ajc$tjp_1);
System.out.println((new StringBuilder("p1 =")).append(p1).toString());
p1.offset(6, 4);
System.out.println((new StringBuilder("p1 =")).append(p1).toString());
save(p1, "test.tmp");
Point p2 = (Point)restore("test.tmp");
System.out.println((new StringBuilder("Had: ")).append(p1).toString());
System.out.println((new StringBuilder("Got: ")).append(p2).toString());
}

static void save(Serializable p, String fn)


{
try

{
System.out.println((new StringBuilder("Writing to file: ")).append(p).toString());
FileOutputStream fo = new FileOutputStream(fn);
ObjectOutputStream so = new ObjectOutputStream(fo);
so.writeObject(p);
so.flush();
}
catch(Exception e)

{
System.out.println(e);
System.exit(1);
}
}

static Object restore(String fn)


{
try

{
System.out.println((new StringBuilder("Reading from file: ")).append(fn).toString());
FileInputStream fi = new FileInputStream(fn);
ObjectInputStream si = new ObjectInputStream(fi);
return si.readObject();
}
catch(Exception e)

{
System.out.println(e);
}
System.exit(1);
return null;
}

//==== 后面的一些代码的添加和修改和在作用在Point上的几乎一样的。不多说了 =====

private static final void setX_aroundBody0(Point point, int i)


{
point.setX(i);
}

private static final void setX_aroundBody1$advice(BoundPoint this, Point p, AroundClosure ajc_aroundClosure, org.aspectj.lang.JoinPoint.StaticPart thisJoinPointStaticPart, String propertyName, int oldX)


{
int oldY = oldX.getSignature().getName().substring("set".length());
int i = thisJoinPointStaticPart.getX();
int j = thisJoinPointStaticPart.getY();
String s = propertyName;
org.aspectj.lang.JoinPoint.StaticPart staticpart = thisJoinPointStaticPart;
setX_aroundBody0(staticpart, p);
if(oldY.equals("X"))
BoundPoint.ajc$inlineAccessMethod$bean_BoundPoint$bean_BoundPoint$firePropertyChange(ajc_aroundClosure, thisJoinPointStaticPart, oldY, i, thisJoinPointStaticPart.getX());
else
BoundPoint.ajc$inlineAccessMethod$bean_BoundPoint$bean_BoundPoint$firePropertyChange(ajc_aroundClosure, thisJoinPointStaticPart, oldY, j, thisJoinPointStaticPart.getY());
}

private static final void setY_aroundBody2(Point point, int i)


{
point.setY(i);
}

private static final void setY_aroundBody3$advice(BoundPoint this, Point p, AroundClosure ajc_aroundClosure, org.aspectj.lang.JoinPoint.StaticPart thisJoinPointStaticPart, String propertyName, int oldX)


{
int oldY = oldX.getSignature().getName().substring("set".length());
int i = thisJoinPointStaticPart.getX();
int j = thisJoinPointStaticPart.getY();
String s = propertyName;
org.aspectj.lang.JoinPoint.StaticPart staticpart = thisJoinPointStaticPart;
setY_aroundBody2(staticpart, p);
if(oldY.equals("X"))
BoundPoint.ajc$inlineAccessMethod$bean_BoundPoint$bean_BoundPoint$firePropertyChange(ajc_aroundClosure, thisJoinPointStaticPart, oldY, i, thisJoinPointStaticPart.getX());
else
BoundPoint.ajc$inlineAccessMethod$bean_BoundPoint$bean_BoundPoint$firePropertyChange(ajc_aroundClosure, thisJoinPointStaticPart, oldY, j, thisJoinPointStaticPart.getY());
}

static final String fileName = "test.tmp";

private static final org.aspectj.lang.JoinPoint.StaticPart ajc$tjp_0; /**//* synthetic field */

private static final org.aspectj.lang.JoinPoint.StaticPart ajc$tjp_1; /**//* synthetic field */

static


{
Factory factory = new Factory("Demo.java", Class.forName("bean.Demo"));
ajc$tjp_0 = factory.makeSJP("method-call", factory.makeMethodSig("1", "setX", "bean.Point", "int:", "newX:", "", "void"), 37);
ajc$tjp_1 = factory.makeSJP("method-call", factory.makeMethodSig("1", "setY", "bean.Point", "int:", "newY:", "", "void"), 38);
}
}
跑一下,Demo.class,还是能得到上面的结果的。
在代码对比上,我做了一些注释,应该会觉得比较明朗了。通过代码对比,我们很容易找出AspectJ是怎样通过pointcut的定义来修改我们的代码。反过来,我们多去理解一下AspectJ是怎样修改我们的代码,并且我们明确我们期待的代码(AspectJ修改后的代码,或者说,不用AOP实现而用普通方法实现的代码)是怎样的,我们也将比较容易定义pointcut了。
posted on 2007-07-14 19:03
三告习习 阅读(3437)
评论(2) 编辑 收藏 所属分类:
AOP