AOP是什么?
AOP (Aspect Oriented Programming,面向切面编程),可以在运行时动态地将代码切入到类中指定方法、指定位置上的一种技术。说白了,就是把横切逻辑从业务逻辑 中抽离出来。哪些属于横切逻辑呢?比如,性能监控、日志、权限控制等等。
AOP相关概念:JointPoint(连接点)
Pointcut(切入点)
Advice(增强)
Adivisor(切面)
Before Advice(前置增强)
After Advice(后置增强)
Around Advice(环绕增强)
Throws Advice(抛出增强)
Introduction Advice(引入增强)
接入方法
1.拷贝如下文件到工程根目录下(是根目录,不是app目录下),命名为aspectj.gradle
import org.aspectj.bridge.IMessage
import org.aspectj.bridge.MessageHandler
import org.aspectj.tools.ajc.Main
final def log = project.logger
final def variants = project.android.applicationVariants
buildscript {
repositories {
maven { url 'http://maven.aliyun.com/nexus/content/groups/public/' }
maven{ url 'http://maven.aliyun.com/nexus/content/repositories/jcenter'}
jcenter()
}
dependencies {
classpath 'org.aspectj:aspectjtools:1.9.1'
}
}
variants.all { variant ->
if (!variant.buildType.isDebuggable()) {
log.debug("Skipping non-debuggable build type '${variant.buildType.name}'.")
return;
}
JavaCompile javaCompile = variant.javaCompile
javaCompile.doLast {
String[] args = ["-showWeaveInfo",
"-1.8",
"-inpath", javaCompile.destinationDir.toString(),
"-aspectpath", javaCompile.classpath.asPath,
"-d", javaCompile.destinationDir.toString(),
"-classpath", javaCompile.classpath.asPath,
"-bootclasspath", project.android.bootClasspath.join(File.pathSeparator)]
log.debug "ajc args: " + Arrays.toString(args)
MessageHandler handler = new MessageHandler(true);
new Main().run(args, handler);
for (IMessage message : handler.getMessages(null, true)) {
switch (message.getKind()) {
case IMessage.ABORT:
case IMessage.ERROR:
case IMessage.FAIL:
log.error message.message, message.thrown
break;
case IMessage.WARNING:
log.warn message.message, message.thrown
break;
case IMessage.INFO:
log.info message.message, message.thrown
break;
case IMessage.DEBUG:
log.debug message.message, message.thrown
break;
}
}
}
}
dependencies {
implementation 'org.aspectj:aspectjrt:1.9.1'
}
2.app下的build.gradle文件中增加:
apply from: '../aspectj.gradle'
实际使用样例
(以“限制按钮只允许单击”为例)
- 定义注解
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface SingleClick {
}
- 添加按钮控制实现类
/**
* 避免连续点击
*/
@Aspect
public class SingleClickAspect {
private long lastClickTime = 0;
private String TAG = SingleClickAspect.class.getSimpleName();
private final long MIN_CLICK_DELAY_TIME = 600;
@Pointcut("execution(@com..SingleClick * *(..))")
public void methodAnnotated() {
}
@Around("methodAnnotated()")
public void aroundJoinPoint(ProceedingJoinPoint joinPoint) throws Throwable {
long currentTime = Calendar.getInstance().getTimeInMillis();
if (currentTime - lastClickTime > MIN_CLICK_DELAY_TIME) {//过滤掉600毫秒内的连续点击
if (BuildConfig.DEBUG) {
Log.d(TAG, "点击发生时间:" + currentTime);
}
lastClickTime = currentTime;
//执行原方法
joinPoint.proceed();
}
else
{
Log.d(TAG, "点击事件被过滤");
}
}
}
- 使用
@Override
protected void onCreate(Bundle savedInstanceState) {
findViewById(R.id.button).setOnClickListener(this);
}
@SingleClick
@Override
public void onClick(View v) {
Toast.makeText(MainActivity.this, "我被点击了", Toast.LENGTH_SHORT).show();
}
- 按钮点击后,后台打印日志
D/SingleClickAspect: 点击发生时间:1554689576613
D/SingleClickAspect: 点击事件被过滤
D/SingleClickAspect: 点击事件被过滤
Demo源代码
https://gitee.com/cxyzy1/aop_demo.git
参考资料https://www.jianshu.com/p/c66f4e3113b3
https://www.jianshu.com/p/f577aec99e17
利用aop监控方法耗时(hugo): https://yq.aliyun.com/articles/7104
安卓开发技术分享: https://blog.csdn.net/yinxing2008/article/details/84555061 点击关注专栏,查看最新技术分享 更多技术总结好文,请关注:「程序园中猿」