随笔-35  评论-97  文章-0  trackbacks-0

在前面《[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 =(00)
Property X changed from 
0.0 to 5.0
Property Y changed from 
0.0 to 2.0
p1 
=(52)
Property X changed from 
5.0 to 6.0
Property Y changed from 
2.0 to 3.0
p1 
=(63)
Property X changed from 
6.0 to 12.0
Property Y changed from 
3.0 to 7.0
p1 
=(127)
Writing to file: (
127)
Reading from file: test.tmp
Had: (
127)
Got: (
127)

 

好,跟上次一样,将编译的代码反编来对照一下。看看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(
52);
    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(
64);
    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 三告习习 阅读(3413) 评论(2)  编辑  收藏 所属分类: AOP

评论:
# re: [AspectJ] 明明白白AspectJ (2) 2011-09-21 10:03 | tianzhijun
请问你有使用aop.xml 在加载时装入的例子吗?包括目标类和方面类的完整例子  回复  更多评论
  
# re: [AspectJ] 明明白白AspectJ (2) 2011-09-21 10:04 | tianzhijun
或者你能不能写个例子给我学习学习。我的邮箱是tzj163@163.com. 谢谢  回复  更多评论
  

只有注册用户登录后才能发表评论。


网站导航: