在前面《[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
三告习习 阅读(3429)
评论(2) 编辑 收藏 所属分类:
AOP