AspectJ工作原理和学习总结

AspectJ是什么?AspectJ能干什么?AspectJ是怎么干活的?

  1. AspectJ是什么

    AspectJ是一个代码生成工具(Code Generator)。
    AspectJ语法就是用来定义代码生成规则的语法。您如果使用过Java Compiler Compiler (JavaCC),您会发现,两者的代码生成规则的理念惊人相似。
    AspectJ有自己的语法编译工具,编译的结果是Java Class文件,运行的时候,classpath需要包含AspectJ的一个jar文件(Runtime lib)。
    AspectJ和xDoclet的比较。AspectJ和EJB Descriptor的比较。

  2. AspectJ能干什么?

     AOP是Object Oriented Programming(OOP)的补充。
    OOP能够很好地解决对象的数据和封装的纵向问题,却不能很好的解决Aspect("方面")分离的横向问题

  3. 使用价值

    认证、事务、日志等等

    如:你已经写好一个功能,有一天客户提出一个需求,需要对调用这个服务的用户进行权限认证,这时候通过AspectJ实现一个AOP是你的首选。

  4. AspectJ是怎么干活的?

    182022_C3Yb_1458864.png

    背景:定义一个Class,如果需要对这个Class的get和set方法进行进行切入

    实现方案:

    一、定义aj规则文件,通过调用call方法实现around切入

    二、定义aj规则文件,通过调用execution方式实现around切入

    过程:定义一个Class,定义一个编译规则,然后反编译class我们看工作过程 

    实现原理:通过定义aj规则文件,由AspectJ编译器扫描包内的aj文件进行规则读取,然后对java代码进行包装后编译成class文件,这个class文件可以被AspectJ的runtime识别并工作,所以在使用AspectJ时一定要引入aspectj.runtime包

     

    方案一:定义aj规则文件,通过调用call方法实现around切入

    Object1.java

package bean;
public class Object1 {
 private int x=1;
 public int getInfo(){
  
  return this.x;
 }
 
 public void setInfo(int x){
  this.x=x;
 }
}

Demo1BoundObject1.aj

package bean;
aspect Demo1BoundObject1 {
 pointcut setter(Object1 object1): call(void Object1.set*(*))&&target(object1);
 void around(Object1 object1): setter(object1){
  String name = thisJoinPointStaticPart.getSignature().getName();
  System.out.println("before :" + name);
  proceed(object1);
  System.out.println("after :" + name);
 }
 pointcut getter(Object1 object1): call(int Object1.get*())&&target(object1);
 int around(Object1 object1): getter(object1){
  String name = thisJoinPointStaticPart.getSignature().getName();
  System.out.println("before :" + name);
  return proceed(object1);
 }

}

 Demo1.java

 

package bean;
public class Demo1 {
 public static void main(String[] args){
  
  Object1 obj=new Object1();
  obj.setInfo(2);
  obj.getInfo();
  
 }
}

 进行反编译:

    Demo1.class

// Decompiled by DJ v3.11.11.95 Copyright 2009 Atanas Neshkov  Date: 2014/7/4 16:12:27
// Home Page: http://members.fortunecity.com/neshkov/dj.html  http://www.neshkov.com/dj.html - Check often for new version!
// Decompiler options: packimports(3) 
// Source File Name:   Demo1.java
package bean;
import java.io.PrintStream;
import org.aspectj.lang.Signature;
import org.aspectj.runtime.internal.AroundClosure;
import org.aspectj.runtime.reflect.Factory;
// Referenced classes of package bean:
//            Object1, Demo1BoundObject1
public class Demo1
{
    public Demo1()
    {
    }
    public static void main(String args[])
    {
        Object1 obj = new Object1();
        byte byte0 = 2;
        Object1 object1 = obj;
        setInfo_aroundBody1$advice(object1, byte0, Demo1BoundObject1.aspectOf(), object1, null, ajc$tjp_0);
        Object1 object1_1 = obj;
        getInfo_aroundBody3$advice(object1_1, Demo1BoundObject1.aspectOf(), object1_1, null, ajc$tjp_1);
    }
    private static final void setInfo_aroundBody0(Object1 object1, int i)
    {
        object1.setInfo(i);
    }
    private static final void setInfo_aroundBody1$advice(Object1 target, int x, Demo1BoundObject1 ajc$aspectInstance, Object1 object1, AroundClosure ajc$aroundClosure, org.aspectj.lang.JoinPoint.StaticPart thisJoinPointStaticPart)
    {
        String name = thisJoinPointStaticPart.getSignature().getName();
        System.out.println((new StringBuilder("before :")).append(name).toString());
        AroundClosure aroundclosure = ajc$aroundClosure;
        Object1 object1_1 = object1;
        setInfo_aroundBody0(object1_1, x);
        System.out.println((new StringBuilder("after :")).append(name).toString());
    }
    private static final int getInfo_aroundBody2(Object1 object1)
    {
        return object1.getInfo();
    }
    private static final int getInfo_aroundBody3$advice(Object1 target, Demo1BoundObject1 ajc$aspectInstance, Object1 object1, AroundClosure ajc$aroundClosure, org.aspectj.lang.JoinPoint.StaticPart thisJoinPointStaticPart)
    {
        String name = thisJoinPointStaticPart.getSignature().getName();
        System.out.println((new StringBuilder("before :")).append(name).toString());
        AroundClosure aroundclosure = ajc$aroundClosure;
        Object1 object1_1 = object1;
        return getInfo_aroundBody2(object1_1);
    }
    private static void ajc$preClinit()
    {
        Factory factory = new Factory("Demo1.java", bean/Demo1);
        ajc$tjp_0 = factory.makeSJP("method-call", factory.makeMethodSig("1", "setInfo", "bean.Object1", "int", "x", "", "void"), 8);
        ajc$tjp_1 = factory.makeSJP("method-call", factory.makeMethodSig("1", "getInfo", "bean.Object1", "", "", "", "int"), 9);
    }
    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 
    {
        ajc$preClinit();
    }
}

 Object1.class

// Decompiled by DJ v3.11.11.95 Copyright 2009 Atanas Neshkov  Date: 2014/7/4 16:14:31
// Home Page: http://members.fortunecity.com/neshkov/dj.html  http://www.neshkov.com/dj.html - Check often for new version!
// Decompiler options: packimports(3) 
// Source File Name:   Object1.java
package bean;

public class Object1
{
    public Object1()
    {
        x = 1;
    }
    public int getInfo()
    {
        return x;
    }
    public void setInfo(int x)
    {
        this.x = x;
    }
    private int x;
}

 

方案二、定义aj规则文件,通过调用execution方式实现around切入

    Demo1.java

package bean;
public class Demo1 {
 public static void main(String[] args){
  
  Object1 obj=new Object1();
  obj.setInfo(2);
  obj.getInfo();
  
 }
}

 

Object1.java

package bean;
public class Object1 {
 private int x=1;
 public int getInfo(){
  
  return this.x;
 }
 
 public void setInfo(int x){
  this.x=x;
 }
}

Demo1BoundObject1.aj

package bean;
aspect Demo1BoundObject1 {
 pointcut bankMethods(Object1 object1) : (execution (* Object1.get*()) || execution (* Object1.set*(*)))&&target(object1);
 Object around(Object1 object1): bankMethods(object1)
   {
  // 验证account是否为合法用户
  String name = thisJoinPointStaticPart.getSignature().getName();
  System.out.println("bankMethods before :" + name);
  Object result = proceed(object1);
  return result;
 }

}

Demo1.class

// Decompiled by DJ v3.11.11.95 Copyright 2009 Atanas Neshkov  Date: 2014/7/4 16:22:53
// Home Page: http://members.fortunecity.com/neshkov/dj.html  http://www.neshkov.com/dj.html - Check often for new version!
// Decompiler options: packimports(3) 
// Source File Name:   Demo1.java
package bean;

// Referenced classes of package bean:
//            Object1
public class Demo1
{
    public Demo1()
    {
    }
    public static void main(String args[])
    {
        Object1 obj = new Object1();
        obj.setInfo(2);
        obj.getInfo();
    }
}

Object1.class

// Decompiled by DJ v3.11.11.95 Copyright 2009 Atanas Neshkov  Date: 2014/7/4 16:23:17
// Home Page: http://members.fortunecity.com/neshkov/dj.html  http://www.neshkov.com/dj.html - Check often for new version!
// Decompiler options: packimports(3) 
// Source File Name:   Object1.java
package bean;
import java.io.PrintStream;
import org.aspectj.lang.Signature;
import org.aspectj.runtime.internal.AroundClosure;
import org.aspectj.runtime.internal.Conversions;
import org.aspectj.runtime.reflect.Factory;
// Referenced classes of package bean:
//            Demo1BoundObject1
public class Object1
{
    public Object1()
    {
        x = 1;
    }
    public int getInfo()
    {
        return Conversions.intValue(getInfo_aroundBody1$advice(this, Demo1BoundObject1.aspectOf(), this, null, ajc$tjp_0));
    }
    public void setInfo(int x)
    {
        int i = x;
        setInfo_aroundBody3$advice(this, i, Demo1BoundObject1.aspectOf(), this, null, ajc$tjp_1);
    }
    private static final int getInfo_aroundBody0(Object1 ajc$this)
    {
        return ajc$this.x;
    }
    private static final Object getInfo_aroundBody1$advice(Object1 ajc$this, Demo1BoundObject1 ajc$aspectInstance, Object1 object1, AroundClosure ajc$aroundClosure, org.aspectj.lang.JoinPoint.StaticPart thisJoinPointStaticPart)
    {
        String name = thisJoinPointStaticPart.getSignature().getName();
        System.out.println((new StringBuilder("bankMethods before :")).append(name).toString());
        AroundClosure aroundclosure = ajc$aroundClosure;
        Object1 object1_1 = object1;
        Object result = Conversions.intObject(getInfo_aroundBody0(object1_1));
        return result;
    }
    private static final void setInfo_aroundBody2(Object1 ajc$this, int x)
    {
        ajc$this.x = x;
    }
    private static final Object setInfo_aroundBody3$advice(Object1 ajc$this, int x, Demo1BoundObject1 ajc$aspectInstance, Object1 object1, AroundClosure ajc$aroundClosure, org.aspectj.lang.JoinPoint.StaticPart thisJoinPointStaticPart)
    {
        String name = thisJoinPointStaticPart.getSignature().getName();
        System.out.println((new StringBuilder("bankMethods before :")).append(name).toString());
        AroundClosure aroundclosure = ajc$aroundClosure;
        Object1 object1_1 = object1;
        setInfo_aroundBody2(object1_1, x);
        Object result = null;
        return result;
    }
    private static void ajc$preClinit()
    {
        Factory factory = new Factory("Object1.java", bean/Object1);
        ajc$tjp_0 = factory.makeSJP("method-execution", factory.makeMethodSig("1", "getInfo", "bean.Object1", "", "", "", "int"), 6);
        ajc$tjp_1 = factory.makeSJP("method-execution", factory.makeMethodSig("1", "setInfo", "bean.Object1", "int", "x", "", "void"), 11);
    }
    private int x;
    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 
    {
        ajc$preClinit();
    }
}

 

转载于:https://my.oschina.net/u/1458864/blog/287389

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
AspectJ是一种基于Java语言的面向切面编程(AOP)的扩展。它通过在编译期间将切面代码织入到目标代码中,实现了对横切关注点的模块化和重用。 AspectJ的实现原理主要包括以下几个步骤: 1. 编译器扩展:AspectJ通过扩展Java编译器,添加了对切面语法的支持。在编译Java源代码时,AspectJ编译器会解析切面文件中的切点和通知,并将其转换为字节码文件。 2. 切点匹配:AspectJ使用切点表达式来定义切点,切点表达式可以根据方法的签名、注解、访问修饰符等条件来匹配目标代码中的连接点。AspectJ编译器会根据切点表达式在目标代码中找到匹配的连接点。 3. 通知织入:一旦找到匹配的连接点,AspectJ会将切面中定义的通知代码织入到目标代码中。通知可以分为前置通知、后置通知、环绕通知等,它们会在目标代码执行前、后或者替代目标代码执行。 4. 字节码增强:AspectJ通过修改目标代码的字节码来实现通知的织入。它会在目标代码中插入切面代码,并调整字节码中的跳转指令,以确保通知的正确执行顺序。 5. 运行时支持:AspectJ还提供了运行时的支持,包括切面实例的创建和管理、连接点的动态绑定、通知的执行等。在程序运行时,AspectJ会根据切面的定义和连接点的匹配情况来决定是否执行通知。 总的来说,AspectJ通过编译器扩展和字节码增强的方式,将切面代码织入到目标代码中,实现了对横切关注点的模块化和重用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值