APT和AOP在android那些事情

APT和AOP在android那些事情

業務背景

apt

你們對eventbus應該不會陌生吧,eventbus是一個很是優秀的事件總線框架,在設計模式中,有點相似觀察者模式,只不過一個升級版本的觀察者模式,而且發送跟接收是切割的,解決不少讓人頭疼的內存泄漏問。其中eventbus所用到的技術就是apt,若是你們在項目中有使用到觀察者模式,不妨用eventbus來改善一下。java

aop

想象一個業務場景,業務要統計activity的啓動耗時,也就是oncreate,onstart這些生命週期方法的耗時,一種原始的方式就是在每一個activity的生命週期中添加劇復的代碼,好比:android

@Override
    protected void onCreate(Bundle savedInstanceState) {
        long start=System.currentTimeMillis();
        super.onCreate(savedInstanceState);  //1
        setContentView(R.layout.activity_main);
        long spend=System.currentTimeMillis()-start; //2
    }
複製代碼

想一想一個activity那麼多生命週期,一個android項目那麼多activity,是否是很繁瑣呢。這時候aop就出場了,爲何不用谷歌親兒子apt呢,由於apt一個比較大的侷限性是:沒法在當前類添加刪除代碼,只能建立一個新的類。簡單點歸納就是aop是一個比apt更強大的代碼生成框架。編程

簡介

  • APT:(Annotation Processing Tool)即註解處理器,是一種註解處理的工具,用來在編譯器掃描以及處理註解。以註解做爲橋樑,經過預先設定好的代碼規則來生成對應的Java代碼
  • AOP:AOP爲Aspect Oriented Programming的縮寫,意爲:面向切面編程。因此這裏所表明的實際上是一種思想,實現這個思想的技術有:ASPECTJ,ASM,JAVASIST,主要是這三個派系
    ## 對比
能力 APT AOP
建立新類 y y
修改當前類 n y
實現技術 AutoService ASPECTJ,ASM,JAVASIST
註解 y y
sdk代碼修改 n y

android打包流程

android官方文檔
build-process_2x設計模式

上一張圖中,compilers階段實際上是有不少個transform組成的
4821599-9f88c2f9936af805bash

其中apt,aop都是做用於compilers階段apt做用於class -->.dex階段,aop做用於class-->.dex或者jar-->.dex階段。能夠進一步看到aop更增強大網絡

使用小建議

apt,aop雖然可以減小不少重複代碼量,代碼結構優化,可是也看出來了,沒有源代碼,不利於排查問題,因此使用者必定要剋制,不是這兩個技術很黑科技就喜歡去使用,不然就是給本身的項目埋下風險。同窗編寫這些apt,aop代碼的同窗必定要留夠足夠的調試信息,方便後續的問題追蹤框架

細講apt

其實網絡上已經有不少優秀apt的案例,就不想重複的編寫這個demo.貼一個推薦的案例
apt案例ide

細講aop

asm實現

用來動態生成類或者加強既有類的功能,ASM是能夠直接產生二進制 class 文件,也能夠在類被加載入 Java 虛擬機以前動態改變類行爲,底層字節碼框架,操縱的級別是底層JVM的彙編指令級別,這要求ASM使用者要對class組織結構和JVM彙編指令有必定的瞭解。工具

整體思路講解post

  • 註冊transform,接收編譯階段代碼的輸入,這裏主要有class和jar包
  • 使用java的jarfile接口解析jar包,而且得到jar包裏面的class文件
JarFile jarFile = new JarFile(inFile)
  Enumeration<JarEntry> entries = jarFile.entries()
複製代碼
  • 使用asm藉口解析jar包裏面的class,更改本身想要的代碼操做,建議使用asm5版本,gradle默認會有這個sdk,無需集成,示例:
ClassReader reader = new ClassReader(entryBytes)
ClassWriter classWriter = new ClassWriter(reader, ClassWriter.COMPUTE_MAXS);
ClassVisitor visitor = new MyClassVisitor(classWriter)
複製代碼
  • 不管更改與否jar包或者class,都要將文件拷貝到下一個輸入位置,參考示例:
File outFile = transformInvocation.outputProvider.getContentLocation(
                                    jarInput.file.absolutePath,
                                    jarInput.contentTypes,
                                    jarInput.scopes,
                                    Format.JAR)
FileUtils.copyFile(jarInput.file, outFile)
複製代碼

網上有一個很是好的講解,而且有示例源碼:
案例

aspectj實現

aspectj是經過註解來實現aop的切面方案,也是最容易上手的一個方案
案例

javassit實現

案例

總結

上面的講究都是引用了其餘人的講解成果,後面會輸出我的編寫demo的文章,更加細緻的講解aop這塊,固然估計可能沒有我如今所引用的案例優秀,透徹。

但願個人文字能給你帶來幫助,同時也歡迎關注我的公衆號,個人全部文章第一手信息回優先發布這裏。我的公衆號:河邊的小黑屋

相關文章
相關標籤/搜索