AOP之AspectJ技术总汇

这几天在研究aspectj的使用方法,所以,顺便写个博客总结下。


一、不带参数的常规写法:


1.具体的逻辑处理类:

@Aspect   //必须使用@AspectJ标注,这样class DemoAspect就等同于 aspect DemoAspectpublic class DemoAspect {
    static final String TAG = "DemoAspect";
    /*
    @Pointcutpointcut是一个注解,这个注解是针对一个函数的,getTimeout()
    其实它代表了这个pointcut的名字。Pointcut后面跟的是该注解被调用的限制条件,比如此处限制为是该MainActivity下以get开头的方法。
    */
    @Pointcut("execution(* com.victor.aspectj.activity.MainActivity.get*(..))")
    public void getTimeout(){};  //注意,这个函数必须要有实现,否则Java编译器会报错

    /*
    @Before:这就是Beforeadvice,对于afterafter -returning,和after-throwing。对于的注解格式为
    @After@AfterReturning@AfterThrowingBefore后面跟的是pointcut名字,然后其代码块由一个函数来实现。
    */
    @Before("getTimeout()")
    public void test(JoinPoint joinPoint){
        Log.e(TAG, joinPoint.toShortString());
    }
}


2,Annotation类:

@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.METHOD })
public @interface DemoTrace {}

3.使用方式

@DemoTrace
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}

二、需要带参数的写法


1.首先,申明annotation时就必须加入方法:

//第一个@Target表示这个注解只能给函数使用
//第二个@Retention表示注解内容需要包含的Class字节码里,属于运行时需要的。
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface CheckLoginAnnotation {//@interface用于定义一个注解。
    public boolean isLogin();  // isLogin是一个函数,其实代表了注解里的参数,在需要的地方需要调用该方法获取参数
}

2.在对应的AspectJ中的potincut中:

@Pointcut("execution(@com.victor.aspectj.CheckLoginAnnotation * *(..)) && @annotation(ann)")
public void checkPermssion(CheckLoginAnnotation ann){};
@annotation(ann)其实就是限制该注解需要传入一个参数


3.具体参数的使用

/*
接下来是adviceadvice的真正功能由check函数来实现,这个check函数第二个参数就是我们想要
的注解。在实际运行过程中,AspectJ会把这个信息从JPoint中提出出来并传递给check函数。
*/
@After("checkPermssion(checkLoginAnnotation)")
public void check(JoinPoint joinPoint, CheckLoginAnnotation checkLoginAnnotation){
    MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
    String className = methodSignature.getDeclaringType().getSimpleName();
    String methodName = methodSignature.getName();
    Log.e(TAG, "className = " + className + " methodName = " + methodName);
    boolean isLogin = checkLoginAnnotation.isLogin();
    Log.e(TAG, "Is logined " + isLogin);

    return;
}

最后是通过调用checkLoginAnnotation.isLogin()方法来获取参数的。


另外,通过joinPoint.getArgs();方法可以获取到被注解方法的参数;


4.调用方式

@CheckLoginAnnotation(isLogin = true)
public boolean setContent() {
    return true;
}

三、advice的类型


关键词

说明

 

示例

before()

before advice

表示在JPoint执行之前,需要干的事情

after()

after advice

表示JPoint自己执行完了后,需要干的事情。

after():returning(返回值类型)

after():throwing(异常类型)

returning和throwing后面都可以指定具体的类型,如果不指定的话则匹配的时候不限定类型

假设JPoint是一个函数调用的话,那么函数调用执行完有两种方式退出,一个是正常的return,另外一个是抛异常。

注意,after()默认包括returning和throwing两种情况

返回值类型 around()

before和around是指JPoint执行前或执行后备触发,而around就替代了原JPoint

around是替代了原JPoint,如果要执行原JPoint的话,需要调用proceed


before和after都很好理解,传参的话按照上面的步骤来就可以了,但是我好像发现在传参的时候,只能传入常量,这个就有点蛋疼了,可能还需要继续挖掘才能发现怎么传变量吧,如果你知道了可以告诉我哦。

主要想说的是关于around()的使用,这个获取会用的相对多些。


四、around() advice类型注解的使用


1.获取方法中返回的参数

@Around("execution(@org.android10.gintonic.annotation.DebugTrace * *(..))")
public Object getMethodParams(ProceedingJoinPoint joinPoint) throws Throwable {
    MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
    String className = methodSignature.getDeclaringType().getSimpleName();
    String methodName = methodSignature.getName();
    DebugLog.log("className", "className = " + className + " methodName = " + methodName);

    Object result = joinPoint.proceed();
    Log.e("result", "" + result);

    return result;
}
 

调用方法:

@DebugTrace
public int getTestParams() {
    return 123;
}

最后打印出来的结果是:123。


2.覆盖原方法

有时候我们我们不需要调用原来的方法时,只要注释掉joinPoint.proceed();方法即可。

// Object result = joinPoint.proceed();



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值