android Aspectj實(shí)踐問題

一些需要知道的:

  1. Aspectj在android中却音,都是通過注解完成庶柿,如@AspectJ,@Pointcut....看铆。
  2. Aspectj的代碼需要專門的編譯器編譯才能使用,在android中剩彬,通過添加一些gradle代碼酷麦,來達(dá)到,這篇文章有介紹喉恋。
  3. 具體學(xué)習(xí)aspectj可以參考這里
  4. 遇到aspectj無法匹配到方法沃饶,或者無效時(shí),請(qǐng)先查看message編譯信息轻黑,以此定位問題糊肤。常見的如 invalid pointcut xxxx。


    編譯信息
  5. AspectjX會(huì)和帶有TransForm功能的插件相沖突氓鄙,常見的有: retroLambda馆揉,butterKnife好像也是。

幾種引入aspectj的方法

1. 依賴aspectj

這種方法并不在此篇文章講述范圍中抖拦,如果需要升酣,可以點(diǎn)擊這里

2. 使用滬江aspectjX插件

滬江公司出的一款aspect插件态罪,只需要在 項(xiàng)目.gradle文件中添加

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


bulid.gradle(相關(guān) module)
apply plugin: 'android-aspectjx'

之后你就可以愉快的使用AspectJ進(jìn)行切面代碼編寫了噩茄。
如果遇到gradle報(bào)錯(cuò),但是原因是空复颈,如:

app:transformClassesWithRetrolambdaForDebug error

那么請(qǐng)使用下面的方法绩聘,這個(gè)錯(cuò)誤沒有辦法解決,它的原因是:Transform 插件沖突【遥可以查看這里

一些問題

每次都需要在gradle中配置一大段代碼驯遇,來使gradle支持Aspectj代碼的編譯芹彬,有沒有簡單的辦法蓄髓?

這問題好解決,封裝唄舒帮,也就是自定義一個(gè)gradle插件來專門干這個(gè)事情会喝。

  1. 創(chuàng)建一個(gè)module(java),module名字必須是buildsrc玩郊,然后刪除java文件夾肢执,只留下src/main。(不明白可以直接看下面的包結(jié)構(gòu))
  2. 在src/main文件夾下新建一個(gè)目錄為 groovy译红,然后在groovy中预茄,創(chuàng)建一個(gè)包(包名無所謂,只是最后你其他模塊應(yīng)用這個(gè)插件時(shí)候侦厚,是根據(jù)包名應(yīng)用)
  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. 在剛才的包中創(chuàng)建一個(gè)文件刨沦,后綴名為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) {
        //得到當(dāng)前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編譯結(jié)束!");
        System.out.println("========================");

    }
}
  1. clean -》 make 不出意外想诅,你就能看到編譯信息了
編譯信息
  1. 最后預(yù)覽一下整體結(jié)構(gòu)
buildsrc包結(jié)構(gòu)
  1. 其他模塊依賴這個(gè)插件
apply plugin: com.hxh.aspjplugin.AspectjPlugin

當(dāng)然召庞,自定義gradle插件并不止這一種方法,你可以參考這里来破,我使用的這篇文章中第二種方法篮灼。

aspj無效,或者無法匹配到方法
  1. 檢查表達(dá)式是否正確徘禁,如果你的表達(dá)式是這樣的(它不是錯(cuò)誤的):
    //應(yīng)用了DataSave注解诅诱,并且有個(gè)參數(shù)為ann
    public final String method_piex1 = "execution(@routerlib.hxh.com.corelib_annotation1.annotation.DataSave * *(..)) && @annotation(ann)";
    //上面的表達(dá)式并不是錯(cuò)誤的,但是在你仔細(xì)檢查表達(dá)式?jīng)]發(fā)現(xiàn)問題的話晌坤,那么你可以這樣描述你的表達(dá)式
    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時(shí)候)

當(dāng)如上都否定時(shí)候骤菠,如果你使用的是自定義gradle插件方法它改,而且當(dāng)前自定義的gradle插件是一種可發(fā)布狀態(tài)的,那么請(qǐng)改為【針對(duì)當(dāng)前項(xiàng)目的gradle插件】商乎,可以參考這里央拖。

使用AspectjX,然后編譯一直不通過,而且錯(cuò)誤信息還是空

上面有相關(guān)解釋鲜戒,所以专控,請(qǐng)更換引入aspectj的方式。

使用JDK1.8 的問題

當(dāng)你遇到遏餐,編譯正常通過伦腐,但是aspectj的代碼就是不執(zhí)行的時(shí)候,錯(cuò)誤的信息為:

Invalid byte tag in constant pool 18

如果你當(dāng)前應(yīng)用的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()
}
編譯出現(xiàn) No such property: project for class: com.android.build.gradle.LibraryPlugin的問題

這是因?yàn)镚radle 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)

持續(xù)更新中....

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末粹庞,一起剝皮案震驚了整個(gè)濱河市咳焚,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌庞溜,老刑警劉巖革半,帶你破解...
    沈念sama閱讀 211,561評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異流码,居然都是意外死亡又官,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,218評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門旅掂,熙熙樓的掌柜王于貴愁眉苦臉地迎上來赏胚,“玉大人,你說我怎么就攤上這事商虐【踉模” “怎么了?”我有些...
    開封第一講書人閱讀 157,162評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵秘车,是天一觀的道長典勇。 經(jīng)常有香客問我,道長叮趴,這世上最難降的妖魔是什么割笙? 我笑而不...
    開封第一講書人閱讀 56,470評(píng)論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮眯亦,結(jié)果婚禮上伤溉,老公的妹妹穿的比我還像新娘。我一直安慰自己妻率,他們只是感情好乱顾,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,550評(píng)論 6 385
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著宫静,像睡著了一般走净。 火紅的嫁衣襯著肌膚如雪券时。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,806評(píng)論 1 290
  • 那天伏伯,我揣著相機(jī)與錄音橘洞,去河邊找鬼。 笑死说搅,一個(gè)胖子當(dāng)著我的面吹牛炸枣,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播蜓堕,決...
    沈念sama閱讀 38,951評(píng)論 3 407
  • 文/蒼蘭香墨 我猛地睜開眼抛虏,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了套才?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,712評(píng)論 0 266
  • 序言:老撾萬榮一對(duì)情侶失蹤慕淡,失蹤者是張志新(化名)和其女友劉穎背伴,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體峰髓,經(jīng)...
    沈念sama閱讀 44,166評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡傻寂,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,510評(píng)論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了携兵。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片疾掰。...
    茶點(diǎn)故事閱讀 38,643評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖徐紧,靈堂內(nèi)的尸體忽然破棺而出静檬,到底是詐尸還是另有隱情,我是刑警寧澤并级,帶...
    沈念sama閱讀 34,306評(píng)論 4 330
  • 正文 年R本政府宣布拂檩,位于F島的核電站,受9級(jí)特大地震影響嘲碧,放射性物質(zhì)發(fā)生泄漏稻励。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,930評(píng)論 3 313
  • 文/蒙蒙 一愈涩、第九天 我趴在偏房一處隱蔽的房頂上張望望抽。 院中可真熱鬧,春花似錦履婉、人聲如沸煤篙。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,745評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽舰蟆。三九已至趣惠,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間身害,已是汗流浹背味悄。 一陣腳步聲響...
    開封第一講書人閱讀 31,983評(píng)論 1 266
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留塌鸯,地道東北人侍瑟。 一個(gè)月前我還...
    沈念sama閱讀 46,351評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像丙猬,于是被迫代替她去往敵國和親涨颜。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,509評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理茧球,服務(wù)發(fā)現(xiàn)庭瑰,斷路器,智...
    卡卡羅2017閱讀 134,633評(píng)論 18 139
  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 171,769評(píng)論 25 707
  • Spring Boot 參考指南 介紹 轉(zhuǎn)載自:https://www.gitbook.com/book/qbgb...
    毛宇鵬閱讀 46,773評(píng)論 6 342
  • 前言 為什么需要學(xué)Gradle? Gradle 是 Android 現(xiàn)在主流的編譯工具抢埋,雖然在Gradle 出現(xiàn)之...
    真笨笨魚閱讀 1,489評(píng)論 0 0
  • 開始注重養(yǎng)生弹灭。 男人在外,應(yīng)該以事業(yè)為主揪垄,在婚里穷吮,總是承擔(dān)著一家之主的角色,所以他們年輕的時(shí)候饥努,總是想著打拼事業(yè)捡鱼,...
    股韻奇談閱讀 370評(píng)論 0 0