android Aspectj实践问题

一些需要知道的:

  1. Aspectj在android中,都是通过注解完成,如@AspectJ,@Pointcut....。
  2. Aspectj的代码需要专门的编译器编译才能使用,在android中,通过添加一些gradle代码,来达到,这篇文章有介绍
  3. 具体学习aspectj可以参考这里
  4. 遇到aspectj无法匹配到方法,或者无效时,请先查看message编译信息,以此定位问题。常见的如 invalid pointcut xxxx。


    编译信息
  5. AspectjX会和带有TransForm功能的插件相冲突,常见的有: retroLambda,butterKnife好像也是。

几种引入aspectj的方法

1. 依赖aspectj

这种方法并不在此篇文章讲述范围中,如果需要,可以点击这里

2. 使用沪江aspectjX插件

沪江公司出的一款aspect插件,只需要在 项目.gradle文件中添加

build.gradle(project)
dependencies {
        classpath 'com.hujiang.aspectjx:gradle-android-plugin-aspectjx:1.0.10'
        }


bulid.gradle(相关 module)
apply plugin: 'android-aspectjx'

之后你就可以愉快的使用AspectJ进行切面代码编写了。
如果遇到gradle报错,但是原因是空,如:

app:transformClassesWithRetrolambdaForDebug error

那么请使用下面的方法,这个错误没有办法解决,它的原因是:Transform 插件冲突。可以查看这里

一些问题

每次都需要在gradle中配置一大段代码,来使gradle支持Aspectj代码的编译,有没有简单的办法?

这问题好解决,封装呗,也就是自定义一个gradle插件来专门干这个事情。

  1. 创建一个module(java),module名字必须是buildsrc,然后删除java文件夹,只留下src/main。(不明白可以直接看下面的包结构)
  2. 在src/main文件夹下新建一个目录为 groovy,然后在groovy中,创建一个包(包名无所谓,只是最后你其他模块应用这个插件时候,是根据包名应用)
  3. 打开此module的gradle文件,全删,然后放入如下代码(记得同步)
apply plugin: 'groovy'
dependencies {
    compile gradleApi()
    compile localGroovy()
    compile 'com.android.tools.build:gradle:2.3.1'
    compile 'org.aspectj:aspectjtools:1.8.10'
    compile 'org.aspectj:aspectjrt:1.8.10'
}
repositories {
    jcenter()
}
  1. 在刚才的包中创建一个文件,后缀名为groovy,代码:
package com.hxh.aspjplugin
import com.android.build.gradle.AppPlugin
import com.android.build.gradle.LibraryPlugin
import org.aspectj.bridge.IMessage
import org.aspectj.bridge.MessageHandler
import org.aspectj.tools.ajc.Main
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.api.tasks.compile.JavaCompile
public class AspectjPlugin implements Plugin<Project> {

    void apply(Project project) {
        //得到当前module的插件类型,是application还是lib
        System.out.println("========================");
        System.out.println("Aspject开始编译!");
        System.out.println("========================");
        def hasApp = project.plugins.withType(AppPlugin)
        def hasLib = project.plugins.withType(LibraryPlugin)
        if (!hasApp && !hasLib) {
            throw new IllegalStateException("'android' or 'android-library' plugin required.")
        }

        final def log = project.logger
        final def variants
        if (hasApp) {
            variants = project.android.applicationVariants
        } else {
            variants = project.android.libraryVariants
        }

        project.dependencies {
            // TODO this should come transitively
            compile 'org.aspectj:aspectjrt:1.8.6'
        }

        variants.all {
            variant ->

            JavaCompile javaCompile = variant.javaCompile
            javaCompile.doLast {
                String[] args = ["-showWeaveInfo",
                                 "-1.5",
                                 "-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;
                    }
                }
            }
        }

        System.out.println("========================");
        System.out.println("Aspject编译结束!");
        System.out.println("========================");

    }
}
  1. clean -》 make 不出意外,你就能看到编译信息了
编译信息
  1. 最后预览一下整体结构
buildsrc包结构
  1. 其他模块依赖这个插件
apply plugin: com.hxh.aspjplugin.AspectjPlugin

当然,自定义gradle插件并不止这一种方法,你可以参考这里,我使用的这篇文章中第二种方法。

aspj无效,或者无法匹配到方法
  1. 检查表达式是否正确,如果你的表达式是这样的(它不是错误的):
    //应用了DataSave注解,并且有个参数为ann
    public final String method_piex1 = "execution(@routerlib.hxh.com.corelib_annotation1.annotation.DataSave * *(..)) && @annotation(ann)";
    //上面的表达式并不是错误的,但是在你仔细检查表达式没发现问题的话,那么你可以这样描述你的表达式
    public final String method_piex = "@within(routerlib.hxh.com.corelib_annotation1.annotation.DataSave) || @annotation(routerlib.hxh.com.corelib_annotation1.annotation.DataSave)";
  1. 是否引入了aspectj的依赖并且添加了编译aspectj文件的代码 。或者插件(使用aspectjX时候)

当如上都否定时候,如果你使用的是自定义gradle插件方法,而且当前自定义的gradle插件是一种可发布状态的,那么请改为【针对当前项目的gradle插件】,可以参考这里

使用AspectjX,然后编译一直不通过,而且错误信息还是空

上面有相关解释,所以,请更换引入aspectj的方式。

使用JDK1.8 的问题

当你遇到,编译正常通过,但是aspectj的代码就是不执行的时候,错误的信息为:

Invalid byte tag in constant pool 18

如果你当前应用的jdk版本为1.8,那么你要这么做

  • 检查你的aspectj 的版本,让其为1.8.10(包含)以上
apply plugin: 'groovy'
dependencies {
    compile gradleApi()
    compile localGroovy()
    compile 'com.android.tools.build:gradle:2.3.1'
    compile 'org.aspectj:aspectjtools:1.8.10'//这两句
    compile 'org.aspectj:aspectjrt:1.8.10'//这两句
}
repositories {
    jcenter()
}
编译出现 No such property: project for class: com.android.build.gradle.LibraryPlugin的问题

这是因为Gradle 2.3+ 后,配置变了

   "-bootclasspath", project.android.bootClasspath.join(File.pathSeparator)]
                log.debug "ajc args: " + Arrays.toString(args)
变更为:
   "-bootclasspath",android.bootClasspath.join(File.pathSeparator)]
                log.debug "ajc args: " + Arrays.toString(args)

持续更新中....

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 160,108评论 4 364
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,699评论 1 296
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,812评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,236评论 0 213
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,583评论 3 288
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,739评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,957评论 2 315
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,704评论 0 204
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,447评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,643评论 2 249
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,133评论 1 261
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,486评论 3 256
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,151评论 3 238
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,108评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,889评论 0 197
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,782评论 2 277
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,681评论 2 272

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,103评论 18 139
  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 170,577评论 25 707
  • Spring Boot 参考指南 介绍 转载自:https://www.gitbook.com/book/qbgb...
    毛宇鹏阅读 46,375评论 6 343
  • 前言 为什么需要学Gradle? Gradle 是 Android 现在主流的编译工具,虽然在Gradle 出现之...
    真笨笨鱼阅读 1,461评论 0 0
  • 开始注重养生。 男人在外,应该以事业为主,在婚里,总是承担着一家之主的角色,所以他们年轻的时候,总是想着打拼事业,...
    股韵奇谈阅读 354评论 0 0