1. AOP编程:
AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。说白了就是用反射、注解等相关技术来hook原有的方法,来执行自己的逻辑。
2.AspectJ框架:
简介:
AspectJ框架就位我们的AOP编程提供了非常便捷的方式,它是一个面向切面编程的框架。AspectJ是对java的扩展,而且是完全兼容java的,AspectJ定义了AOP语法,它有一个专门的编译器用来生成遵守Java字节编码规范的Class文件。AspectJ还支持原生的Java,只需要加上AspectJ提供的注解即可。在Android开发中,一般就用它提供的注解和一些简单的语法就可以实现绝大部分功能上的需求了。
AspectJ官方网站(下载AspectJ的jar包,更新AspectJ的adt等):http://www.eclipse.org/aspectj/
AspectJ类库参考文档:http://www.eclipse.org/aspectj/doc/released/runtime-api/index.html
AspectJ注解文档:http://www.eclipse.org/aspectj/doc/released/aspectj5rt-api/index.html
android中的应用:
首先在app的build.gradle中引入:
dependencies {
...
implementation 'org.aspectj:aspectjrt:1.9.4'
}
然后在项目的build.gralde中引入对应的编译工具
buildscript {
repositories {
google()
jcenter()
}
dependencies {
...
classpath 'org.aspectj:aspectjtools:1.9.4' //这里的版本注意与引入的jar版本对应起来
}
}
接下来就可以进入撸码阶段了:
1.自定义一个注解,用来做标记,标记在方法上(AspectJ会在编译时替代javac,在被这个注解标记的方法前后插入代码)
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface BehaviorTrace {
String value();
}
2.在要处理的方法添加定义的注解,该方法可以被一个切点关联,关联之后可以理解为切点即该方法
@BehaviorTrace("摇一摇")
public void mShake(View view) {
Log.d("MainActivity","点击了摇一摇");
}
3.创建一个处理切点的类,添加上@Aspect注解
import android.os.SystemClock;
import android.util.Log;
import android.widget.Button;
import com.dn_alan.myapplication.annotation.BehaviorTrace;
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.reflect.MethodSignature;
import java.util.Random;
@Aspect
public class BehaviorTraceAspect {
//定义切面的规则
//1、就再原来的应用中那些注解的地方放到当前切面进行处理
//execution(注解名 注解用的地方)
@Pointcut("execution(@com.dn_alan.myapplication.annotation.BehaviorTrace * *(..))")
public void methodAnnottatedWithBehaviorTrace() {
}
//2、对进入切面的内容如何处理
//@Before 在切入点之前运行
// @After("methodAnnottatedWithBehaviorTrace()")
//@Around 在切入点前后都运行
@Around("methodAnnottatedWithBehaviorTrace()")
public Object weaveJoinPoint(ProceedingJoinPoint joinPoint) throws Throwable {
Log.d("BehaviorTraceAspect","weaveJoinPoint------------");
MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
Object[] args = joinPoint.getArgs(); //获取参数
String className = methodSignature.getDeclaringType().getSimpleName(); //获取类名
String methodName = methodSignature.getName();//获取方法名
String value = methodSignature.getMethod().getAnnotation(BehaviorTrace.class).value();//获取自定义注解传入的参数值
String declaringTypeName = methodSignature.getDeclaringTypeName();
String[] names = methodSignature.getParameterNames(); //获取所有参数的名字
Class[] types = methodSignature.getParameterTypes(); //获取所有参数的类型
long begin = System.currentTimeMillis();
Object result = joinPoint.proceed();
long duration = System.currentTimeMillis() - begin;
if(args[0] instanceof Button){
Button btn= (Button) args[0];
btn.setText("动一动");
}
Log.d("BehaviorTraceAspect", String.format("%s功能:%s类的%s方法执行了,用时%d ms",
value, className, methodName, duration)+"declaringTypeName-------"+declaringTypeName+"names---->"+names[0]+"types--------->"+types[0]);
return result;
}
}
执行效果:
日志输出
Activity中的代码:
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
@BehaviorTrace("摇一摇")
public void mShake(View view) { //这就一个点击事件
Log.d("MainActivity","点击了摇一摇");
try {
Thread.currentThread().sleep(2000);
Log.d("MainActivity","休眠后变为动一动");
} catch (InterruptedException e) {
}
}
}
至此,通过Aspect完成切面编程的小Demo就完成啦!
3.使用场景:
项目中用到的一些事件统计信息,一些界面需登录操作啊等,都可以用此类方式来实现。