Android Studio中AspectJ的简单使用一(自定义PointCut)

    使用自定义注解的方式,步骤如下

     1.创建自定义注解;

     2.创建操作类(切入文件);

     3.调用注解。

    一、创建自定义注解。

      代码如下。

package cm.richeninfo.com.astestaspect20180309.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * Created by wangxiaowu on 2018/3/9  14:08
 * decribe
 * 注解类
 */
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface BehaviorTrace {
    String value();
}

     注意:

       @Target、@Retention、@interface

     备注:

     java中元注解有四个: @Retention @Target @Document @Inherited;
   @Retention:注解的保留位置         
      @Retention(RetentionPolicy.SOURCE)   //注解仅存在于源码中,在class字节码文件中不包含
      @Retention(RetentionPolicy.CLASS)     // 默认的保留策略,注解会在class字节码文件中存在,但运行时无法获得,
      @Retention(RetentionPolicy.RUNTIME)  // 注解会在class字节码文件中存在,在运行时可以通过反射获取到
  
  @Target:注解的作用目标
        @Target(ElementType.TYPE)   //接口、类、枚举、注解
        @Target(ElementType.FIELD) //字段、枚举的常量
        @Target(ElementType.METHOD) //方法
        @Target(ElementType.PARAMETER) //方法参数
        @Target(ElementType.CONSTRUCTOR)  //构造函数
        @Target(ElementType.LOCAL_VARIABLE)//局部变量
        @Target(ElementType.ANNOTATION_TYPE)//注解
        @Target(ElementType.PACKAGE) ///包   
 
     @Document:说明该注解将被包含在javadoc中
 

   @Inherited:说明子类可以继承父类中的该注解


     RetentionPolicy.SOURCE:注解只保留在源文件,当Java文件编译成class文件的时候,注解被遗弃;
     RetentionPolicy.CLASS:注解被保留到class文件,但jvm加载class文件时候被遗弃,这是默认的生命周期;

     RetentionPolicy.RUNTIME:注解不仅被保存到class文件中,jvm加载class文件之后,仍然存在;


二、创建操作类

        代码如下。

package cm.richeninfo.com.astestaspect20180309.aspect;

import android.util.Log;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.annotation.RequiredTypes;
import org.aspectj.lang.reflect.MethodSignature;

import java.util.Objects;

import cm.richeninfo.com.astestaspect20180309.annotation.BehaviorTrace;

/**
 * Created by wangxiaowu on 2018/3/9  14:36
 * decribe
 */
@Aspect
public class BehaviorTraceAspect {

    //关联的注解类cm.richeninfo.com.astestaspect20180309.annotation.BehaviorTrace
    @Pointcut("execution(@cm.richeninfo.com.astestaspect20180309.annotation.BehaviorTrace * *(..))")
     public void methodAnnotatedWithBehaviorTraceAspect(){
        //下面的代码没有执行
        Log.d("system.out","methodAnnotated**********************");
    }

//    @Before("methodAnnotatedWithBehaviorTraceAspect()")
//    public void beforeMethod() throws Throwable{
//        Log.v("system.out","before method is executed");
//    }
//
//    @After("methodAnnotatedWithBehaviorTraceAspect()")
//    public void afterMethod() throws Throwable{
//        Log.v("system.out","after method is executed");
//    }

    //关联的操作methodAnnotatedWithBehaviorTraceAspect()
    @Around("methodAnnotatedWithBehaviorTraceAspect()")
    public Object aroundMethod(ProceedingJoinPoint joinPoint) throws Throwable{
        Object result=null;
        if(null!=joinPoint){
            MethodSignature methodSignature=(MethodSignature)joinPoint.getSignature();
            String className=methodSignature.getDeclaringType().getSimpleName();
            String methodName=methodSignature.getName();
            String funName=methodSignature.getMethod().getAnnotation(BehaviorTrace.class).value();
            Log.d("system.out","arround method is executed.before");

            //统计时间
            long begin=System.currentTimeMillis();
            result=joinPoint.proceed();
            long duration=System.currentTimeMillis()-begin;
            Log.d("system.out",String.format("around method is executed .after 功能:%s,%s类的%s方法执行了,用时%d ms",funName,className,methodName,duration));
            return result;
        }
        return result;
    }
}

     注意:

      类必须要加上@Aspect注解。再声明一个方法作为切点,这个方法需要加上注解: 

      @pointcut(execution(@全类名 * *(. .)))        后面的两个表示*匹配所有的方法名,两个.表示匹配所有的方法参数

    备注:

      AspectJ的切入点表达式中,可以用execution、call。

      对于Call来说:

      Call(Before)      Pointcut{            Pointcut Method     }    Call(After)    对于Execution来说:    Pointcut{        execution(Before)        Pointcut Method        execution(After)    }

三、调用注解

代码如下。

package cm.richeninfo.com.astestaspect20180309;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;

import cm.richeninfo.com.astestaspect20180309.annotation.BehaviorTrace;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        findViewById(R.id.activity_main_tv1).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                testAspect();
            }
        });
    }

    @BehaviorTrace("测试 aspect")
    private int testAspect(){
        Log.v("system.out","testAspect inner is executed");

        return 100;
    }
}
       





你可能感兴趣的:(Android)