Android AOP框架AspectJ使用详解

Android AOP框架AspectJ使用详解,第1张

概述前言之前了解过android的AOP框架,用法主要用来打日志;现在有一个需求需要函数在新线程中执行,并且函数主体执行完之后,在UI线程返回结果。想到手写的话,每次都要newThread的 *** 作,比较麻烦;因此就尝试用注解的

前言

之前了解过androID的AOP框架,用法主要用来打日志;现在有一个需求需要函数在新线程中执行,并且函数主体执行完之后,在UI线程返回结果。想到手写的话,每次都要new Thread的 *** 作,比较麻烦;因此就尝试用注解的方法解决这个问题。

AspectJ的使用核心就是它的编译器,它就做了一件事,将AspectJ的代码在编译期插入目标程序当中,运行时跟在其它地方没什么两样,因此要使用它最关键的就是使用它的编译器去编译代码ajc。ajc会构建目标程序与AspectJ代码的联系,在编译期将AspectJ代码插入被切出的pointcut中,已达到AOP的目的。

因此,无论在什么IDE上(如果使用命令行就可以直接使用ajc编译了),问题就是让IDE使用ajc作为编译器编译代码。

代码实现

注解使用

代码主要通过TraceLog、RunOnNewThread、RunOnNewThreaDWithUICallback这三个注解与AOP容器关联。使用方法如下:

@TraceLog@RunOnNewThreadpublic voID checkAndRestartDownloadTask(final boolean isautoCache) { DownloadManager.getInstance().startService(isautoCache);}@TraceLog@RunOnNewThreaDWithUICallbackpublic Boolean isShowTipsForFirstVIDeoCache(DBqueryCallback<Boolean> callback) { if (!PreferenceClIEnt.is_first_vIDeo_cache_done.getBoolean() &&   (DownloadManager.getInstance().getFinishedTaskSize(true,false) > 0 ||     DownloadManager.getInstance().getFinishedTaskSize(true,true) > 0)) {  PreferenceClIEnt.is_first_vIDeo_cache_done.setBoolean(true);  return true; } return false;}

checkAndRestartDownloadTask方法,希望方法体在一个新的线程执行并打印方法执行的Log;isShowTipsForFirstVIDeoCache方法,希望方法体在一个新的线程执行,并将函数的结果通过DBqueryCallback这个回调回传给UI线程,同时打印方法执行的Log。

AOP容器识别这三个注解,并实现注解解释器。

@Aspectpublic class TudouDownloadAspect { public static final String TAG = TudouDownloadAspect.class.getSimplename(); private static final String THREAD_CALLBACK_POINT_METHOD =   "execution(@com.download.common.aspect.RunOnNewThreaDWithUICallback * *(..,com.download.common.callback.DBqueryCallback))"; private static final String THREAD_CALLBACK_POINT_CONSTRUCTOR =   "execution(@com.download.common.aspect.RunOnNewThreaDWithUICallback *.new(..,com.download.common.callback.DBqueryCallback))"; private static final String THREAD_POINT_METHOD =   "execution(@com.download.common.aspect.RunOnNewThread * *(..))"; private static final String THREAD_POINT_CONSTRUCTOR =   "execution(@com.download.common.aspect.RunOnNewThread *.new(..))"; private static final String LOG_POINT_METHOD =   "execution(@com.download.common.aspect.TraceLog * *(..))"; private static final String LOG_POINT_CONSTRUCTOR =   "execution(@com.download.common.aspect.TraceLog *.new(..))"; @pointcut(THREAD_CALLBACK_POINT_METHOD) public voID methodAnnotateDWithThread(){} @pointcut(THREAD_CALLBACK_POINT_CONSTRUCTOR) public voID constructorAnnotateDWithThread(){} @pointcut(THREAD_POINT_METHOD) public voID methodAnnotateDWithNewThread(){} @pointcut(THREAD_POINT_CONSTRUCTOR) public voID constructorAnnotateDWithNewThread(){} @pointcut(LOG_POINT_METHOD) public voID methodAnnotateDWithLog(){} @pointcut(LOG_POINT_CONSTRUCTOR) public voID constructorAnnotateDWithLog(){} /**  * @RunOnNewThreaDWithUICallback 的注解解释器  * */ @Around("methodAnnotateDWithThread() || constructorAnnotateDWithThread()") public Object wrapNewThreaDWithCallback(final ProceedingJoinPoint joinPoint) throws Throwable {  Log.v(TAG,"in wrapNewThreaDWithCallback");  Object[] obJs = joinPoint.getArgs();  final DBqueryCallback callback = (DBqueryCallback) obJs[obJs.length-1];  new Thread(new Runnable() {   @OverrIDe   public voID run() {    try {     final Object obj = joinPoint.proceed();     DownloadClIEnt.getInstance().mainHandler.post(new Runnable() {      @OverrIDe      public voID run() {       if (obj != null)        callback.querySuccess(obj);       else        callback.queryFail();      }     });    } catch (Throwable throwable) {     throwable.printstacktrace();    }   }  }).start();  return null; } /**  * @RunOnNewThread 的注解解释器  * */ @Around("methodAnnotateDWithNewThread() || constructorAnnotateDWithNewThread()") public voID wrapNewThread(final ProceedingJoinPoint joinPoint) throws Throwable {  Log.v(TAG,"in wrapNewThread");  new Thread(new Runnable() {   @OverrIDe   public voID run() {    try {     joinPoint.proceed();    } catch (Throwable throwable) {     throwable.printstacktrace();    }   }  }).start(); } /**  * @TraceLog 的注解解释器  * */ @Before("methodAnnotateDWithLog() || constructorAnnotateDWithLog()") public voID wrapWithLog(JoinPoint joinPoint) throws Throwable {  Log.v(TAG,"before->" + joinPoint.getTarget().toString() + "---" + joinPoint.getSignature().getname()); }}
@Aspect:声明一个AOP容器 @pointcut:声明一个切入点 @Around:将函数主体包裹起来,在函数主体前、后插入代码 @Before:在函数主体执行之前插入代码

使用Gradle脚本加载AOP容器

buildscript {  repositorIEs {    mavenLocal()    maven { url "https://jitpack.io" }  }  dependencIEs {    classpath 'org.aspectj:aspectjtools:1.8.+' //AspectJ脚本依赖  }} dependencIEs {    compile 'org.aspectj:aspectjrt:1.8.+' //AspectJ 代码依赖  }//AspectJ AOP容器加载脚本final def log = project.loggerfinal def variants = project.androID.libraryVariantsvariants.all { variant ->  JavaCompile javaCompile = variant.javaCompile  javaCompile.dolast {    String[] args = ["-showweaveInfo","-1.5","-inpath",javaCompile.destinationDir.toString(),"-aspectpath",javaCompile.classpath.asPath,"-d","-classpath","-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;      }    }  }}

备注

@RunOnNewThreaDWithUICallback这个注解的匹配规则需要函数的最后一个参数为DBqueryCallback(必须要有一个回调参数,不然怎么回传给UI线程~)。函数的返回值必须和DBqueryCallback的泛型类型一致,因为需要将返回值传入回调当中;

new Thread(new Runnable() {   @OverrIDe   public voID run() {    try {     final Object obj = joinPoint.proceed();     DownloadClIEnt.getInstance().mainHandler.post(new Runnable() {      @OverrIDe      public voID run() {       if (obj != null)        callback.querySuccess(obj);       else        callback.queryFail();      }     });    } catch (Throwable throwable) {     throwable.printstacktrace();    }   }  }).start();

注意final Object obj = joinPoint.proceed();,执行了函数体以后,我们默认取到的是一个Object类型的返回值,所以不能用基本数据类型(bool用Boolean,int用Interger)。还有一点,Java中的null是可以转化为任意类型的,所以就算在函数体直接返回null,执行final Object obj = joinPoint.proceed();,这个类型转化也是不会有问题。亲测有效,可以放心使用

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持编程小技巧。

总结

以上是内存溢出为你收集整理的Android AOP框架AspectJ使用详解全部内容,希望文章能够帮你解决Android AOP框架AspectJ使用详解所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/1143738.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-31
下一篇 2022-05-31

发表评论

登录后才能评论

评论列表(0条)

保存