Android中的AOP

Android中的AOP

什麼是AOP

AOP(Aspect Oriented Program的首字母縮寫)是一種面向切面編程的思想。這種編程思想是相對於OOP(ObjectOriented Programming即面向對象編程)來講的。html

先來講一下你們熟悉的面向對象編程:面向對象的特色是繼承、多態和封裝。而封裝就要求將功能分散到不一樣的對象中去,這在軟件設計中每每稱爲職責分配。實際上也就是說,讓不一樣的類設計不一樣的方法。這樣代碼就分散到一個個的類中去了。這樣作的好處是下降了代碼的複雜程度,使類可重用。可是面向對象的編程天生有個缺點就是分散代碼的同時,也增長了代碼的重複性
好比我但願在項目裏面全部的模塊都增長日誌統計模塊,按照OOP的思想,咱們須要在各個模塊裏面都添加統計代碼,可是若是按照AOP的思想,能夠將統計的地方抽象成切面,只須要在切面裏面添加統計代碼就OK了。java

image.png

其實在服務端的領域AOP已經被玩的風生水起,例如Spring的框架。

代碼demo連接 github.com/xsfelvis/an…android

一、APT + JavaPoet

APT(Annotation Processing Tool 的簡稱),能夠在代碼編譯期解析註解,結合JavaPoet 生成新的 Java 文件,減小手動的代碼輸入。如今有不少主流庫都用上了 APT,好比 Dagger2, ButterKnife, EventBus3 等
更多能夠參考編譯時註解之APTgit

一、定義註解

例如github

@Retention(RetentionPolicy.CLASS)
@Target(ElementType.FIELD)
public @interface BindView {
int value();
}
複製代碼

二、定義Processor派生自AbstractProcessor 而且使用@AutoService標註

AutoService會自動在META-INF文件夾下生成Processor配置信息文件,該文件裏就是實現該服務接口的具體實現類。而當外部程序裝配這個模塊的時候,
就能經過該jar包META-INF/services/裏的配置文件找到具體的實現類名,並裝載實例化,完成模塊的注入編程

三、提取註解信息

在Processor中提取註解信息 結合一些手段去處理,好比JavaPoet,或者 JavaPoet使用指南api

核心點

  • 處理Processor中的 註解信息的套路
  • javapoet中的代碼生成 Elements

二、AspectJ

簡單介紹

  • AspectJ 是使用最爲普遍的 AOP 實現方案,適用於 Java 平臺,官網地址:www.eclipse.org/aspectj/  其中AspectJ 是在靜態織入代碼,即在編譯期注入代碼的
  • AspectJ 提供了一套全新的語法實現,徹底兼容 Java(跟 Java 之間的區別,只是多了一些關鍵詞而已)。同時,還提供了純 Java 語言的實現,經過註解的方式,完成代碼編織的功能。所以咱們在使用 AspectJ 的時候有如下兩種方式
    • 使用 AspectJ 的語言進行開發
    • 經過 AspectJ 提供的註解在 Java 語言上開發
  • 由於最終的目的其實都是須要在字節碼文件中織入咱們本身定義的切面代碼,無論使用哪一種方式接入 AspectJ,都須要使用 AspectJ 提供的代碼編譯工具 ajc 進行編譯。
  • 在 Android Studio 上通常使用註解的方式使用 AspectJ,由於 Android Studio 沒有 AspectJ 插件,沒法識別 AspectJ 的語法(不過在 Intellij IDEA 收費版上可使用 AspectJ 插件),因此後面的語法說明和示例都是以註解的實現方式

術語

  • JoinPoints(鏈接點)

JoinPoints(鏈接點),程序中可能做爲代碼注入目標的特定的點。在AspectJ中能夠做爲JoinPoints的地方包括
安全

image.png

  • PointCuts(切入點)

PointCuts(切入點),其實就是代碼注入的位置。與前面的JoinPoints不一樣的地方在於,其實PointCuts是有條件限定的JoinPoints。好比說,在一個Java源文件中,會有不少的JoinPoints,可是咱們只但願對其中帶有@debug註解的地方纔注入代碼。因此,PointCuts是經過語法標準給JoinPoints添加了篩選條件限定oracle

  • Advice(通知)

Advice(通知),其實就是注入到class文件中的代碼片。典型的 Advice 類型有 before、after 和 around,分別表示在目標方法執行以前、執行後和徹底替代目標方法執行的代碼框架

  • Aspect(切面)

Aspect(切面),Pointcut 和 Advice 的組合看作切面。

  • Weaving

注入代碼(advices)到目標位置(joint points)的過程

三、Javassit

簡介

Javassist做用是在編譯器間修改class文件,與之類似的ASM(熱修復框架女媧)也有這個功能,可讓咱們直接修改編譯後的class二進制代碼,

首先咱們得知道何時編譯完成,而且咱們要趕在class文件被轉化爲dex文件以前去修改。在Transfrom這個api出來以前,想要在項目被打包成dex以前對class進行操做,必須自定義一個Task,而後插入到predex或者dex以前,在自定義的Task中可使用javassist或者asm對class進行操做。而Transform則更爲方便,Transfrom會有他本身的執行時機,不須要咱們插入到某個Task前面。Tranfrom一經註冊便會自動添加到Task執行序列中,而且正好是項目被打包成dex以前。

image.png

經常使用方式

須要配合自定義 GradlePlugin、TransForm,每每在TransForm期間使用Javassit 去完成一些須要的aop,關於自定義Gradle插件這裏就不繼續展開了

ClassPool、CtClass、CtMethod核心類的使用在這裏展現的很詳細。

一、初始化ClassPool設置 二、經過包名取到對應的CtClass 三、CtMethodi插入代碼塊,寫文件,釋放,結束整個注入代碼過程。

結語

這幾種AOP方式各自最大的特色就是編織代碼的時機不一樣,這個須要在使用的時候根據實際須要來,

image.png

上圖中 javaassit和asm也能夠結合apt使用的,好比建立類,不過目前建立類通常都是javapoet,它們只是工具而已 一般aop能夠用來處理如下問題

  • 日誌、監控
  • 登錄
  • 修復第三方代碼,好比第三方jar包
  • hook 某些代碼爲封裝過的安全性更好的代碼, 好比hook系統toast或者Gson等等
  • ……

參考

相關文章
相關標籤/搜索