使用自定义注解的方式,步骤如下
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;
}
}