AOP :: ActionScript 2.0 on As2lib

Posted by PunNeng, Wed Apr 18 21:58:00 UTC 2007

หลังจากลองบน Ruby ไปแล้ว คราวนี้มาถึงตาของ ActionScript บ้าง(ให้ตายเถอะ นานๆ จะได้มาเล่นอะไรบน Flash คิดถึงจริงๆ)

ฝั่ง Ruby ใช้ตัวช่วยคือ AspectR
ฝั่ง ActionScript 2.0 ใช้ตัวช่วยคือ As2lib

เล็กน้อย สำหรับ As2lib
As2lib เป็น open source framework ตัวนึงที่ถูกออกแบบมาให้ทำงานกับ Flash MX 2004+(หนักไปทาง ActionScript 2.0) โดยมันจะไปช่วยในเรื่อง event handling, error handling, logging, overloading and reflections และยังบรรจุ testing framework,input/output(io) framework, aspect-oriented programming (AOP) framework และ regular expression (RegExp) framework(เป็นอีกหนึ่งอย่างที่ผมจะลอง)

เริ่มต้นด้วยการ download As2lib มาติดตั้งกันก่อน

จากนั้น extract เอา src folder มาใช้ โดยการ copy ไปวางไว้ที่ path เดียวกับ file.fla ที่เราจะใช้งาน แล้วก็สร้าง file.fla มาเลย แล้วไป set classpath ก่อน ไปที่ File > Publish Settings เลือก tab ที่เป็น Flash กดปุ่ม Settings (ข้างๆ ActionScript version dropdown) จากนั้นปุ่ม + บนหน้าต่างที่เด้งขึ้นมา แล้วเพิ่ม ./src เข้าไปแล้วกด ok แล้ว save file นี้ไว้บน path เดียวกับ src folder

มาลง code กันบ้าง เริ่มต้นจาก Product class

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
class Product{
  private var price:Number;
  // private var logger:Logger;
  public function Product(){
    price = 0;
    // logger = new Logger();
  }
  public function setPrice(p:Number):Number{
    // logger.writeLog(price + " is changed to " + p);
    price = p;
    return price;
  }
  public function getPrice():Number{
    return price;
  }
}

save เป็น Product.as ไว้ที่ path เดียวกับ file.fla ของเรา มาดู Logger class บ้าง

  1
  2
  3
  4
  5
  6
  7
  8
  9
class Logger{
  function Logger(){
    // open log file
  }
  public function writeLog(msg:String){
    // write msg to log file
    trace(msg);
  }
}

save เป็น Logger.as ไว้ที่ path เดียวกับ file.fla ของเรา จริงๆ แล้ว flash เขียนต่อ file ไม่ได้ แต่มันเป็นแค่ตัวอย่างครับ จะได้เหมือนกับของ Ruby

บน Product class ถ้าเอา comment ออก ก็จะทำงานได้ตามปกติ โดยไม่ต้องอาศัย aspect

ทีนี้ จะมาลองสร้าง aspect กันบ้าง

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
import org.as2lib.aop.Aspect;
import org.as2lib.aop.aspect.AbstractAspect;
import org.as2lib.aop.advice.AbstractAdvice;
import org.as2lib.aop.JoinPoint;

class LoggingAspect extends AbstractAspect implements Aspect {
  private var logger:Logger;
  function LoggingAspect(){
    logger = new Logger();
    addAdvice(AbstractAdvice.BEFORE, getBeforeOperationsPointcut(), beforeOperationsAdvice);
    // addAdvice(AbstractAdvice.AROUND, getOperationsPointcut(), aroundOperationsAdvice);
  }
  private function getOperationsPointcut(Void):String {
    return "execution(Product.setPrice())";
    // or you can use execution(Product.setPrice()) || execution(Product.getPrice()) instead, 
    // an advice will be operated when setPrice or getPrice are invoked.
  }

  private function beforeOperationsAdvice(joinPoint:JoinPoint, args:FunctionArguments) {

    //trace(joinPoint.getInfo().getDeclaringType().getName() + "." + joinPoint.getInfo().getName() + "(" + args + ")");
    //trace("Before: " + Product(joinPoint.getThis()).getPrice());
    logger.writeLog(Product(joinPoint.getThis()).getPrice() + " is changed to " + args);
  }

  private function aroundOperationsAdvice(joinPoint:JoinPoint, args:FunctionArguments) {
    logger.writeLog(Product(joinPoint.getThis()).getPrice() + " is changed to " + args);
    var result = joinPoint.proceed(args);
    logger.writeLog(tick() + " " + joinPoint.getInfo().getDeclaringType().getName() + "#" + joinPoint.getInfo().getName() + ": returned " + result + " and exited");
    return result;
  }
  private function tick():String{
    return new Date().getFullYear() + "-" + new Date().getMonth() + "-" + new Date().getDate();
  }
}

ที่ comment ใน beforeOperationsAdvice ไว้ จะเป็นวิธีการเอาข้อมูลออกมาใช้งาน ไม่ว่าจะเป็น classname, method name หรือว่า arguments ต่างๆ ที่รับเข้ามา เริ่มต้นที่การ import class ต่างๆ เข้ามาใช้งาน ใน constructor

  1
addAdvice(AbstractAdvice.BEFORE, getOperationsPointcut(), beforeOperationsAdvice);

อันนี้เป็นการ set pointcut โดยการใส่ advice และ join point เข้าไป ที่เหลือก็เป็นการประกาศการทำงาน

จากนั้นมาดูการ weave กันบ้าง

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
import org.as2lib.aop.Aspect;
import org.as2lib.aop.Weaver;
import org.as2lib.aop.weaver.SimpleWeaver;

var logging_aspect = new LoggingAspect();
var weaver:SimpleWeaver = new SimpleWeaver();
weaver.addAspect(logging_aspect, [Product]);
weaver.weave();

var product:Product = new Product();
product.setPrice(7);
product.setPrice(5);

code ตรงนี้ ก็ import library ต่างๆ ที่จำเป็น แล้วมาประกาศการ weave (ถ้ามีหลาย class ให้เพิ่มตรง addAspect เอา เป็น [Product, AnyClass] เป็นต้น) แล้วค่อยมาเป็นการประกาศการทำงานบน class ของเรา ซึ่งจะคล้ายๆ กับของ Ruby แต่จริงๆ ผมชอบแบบ AspectJ มากกว่า ที่ไป weave กันตอน compile เอา(บน Ruby เด๋วมีแบบนี้เหมือนกัน ใจเย็นพี่น้อง)

มาดูผลที่ได้

มาลอง Around บ้าง ก็สลับ comment เป็น

  1
  2
// addAdvice(AbstractAdvice.BEFORE, getBeforeOperationsPointcut(), beforeOperationsAdvice);
addAdvice(AbstractAdvice.AROUND, getOperationsPointcut(), aroundOperationsAdvice);

มาดูผลที่ได้

ข้อมูลจาก www.simonwacker.com (as2lib version ใหม่มันมีปัญหา ถ้าลองตามใน site ของ simon wacker จะรันไม่ออก ลองตามของไอ่เหน่งดีกว่า modify ให้แล้ว)

Filed Under: General | Tags: actionscript aop as2lib aspect

Comments

Have your say

A name is required. You may use HTML in your comments.




codegent: we're hiring