1. 程式人生 > >AspectJ介紹(一)

AspectJ介紹(一)

AOP概念

AOP是Aspect Oriented Programming的縮寫,即『面向切面程式設計』。它和我們平時接觸到的OOP都是程式設計的不同思想,OOP,即『面向物件程式設計』,它提倡的是將功能模組化,物件化,而AOP的思想,則不太一樣,它提倡的是針對同一類問題的統一處理,當然,我們在實際程式設計過程中,不可能單純的安裝AOP或者OOP的思想來程式設計,很多時候,可能會混合多種程式設計思想,大家也不必要糾結該使用哪種思想,取百家之長,才是正道

AspectJ

AspectJ實際上是對AOP程式設計思想的一個實踐,當然,除了AspectJ以外,還有很多其它的AOP實現,例如ASMDex,但目前最好、最方便的,依然是AspectJ。

發現問題

當初做自己的專案,有部分程式碼我不想讓別人通過反編譯知道其邏輯,我做過很多防護措施:

  1. 程式碼混淆
  2. 核心方法Native
  3. 動態載入dex,載入dex之前dex檔案加密
  4. 動態載入so
  5. 所有宣告字串加密
  6. 使用3方加固平臺(治標不治本)
  7. 插入程式碼花指令,jui工具編譯方法報錯

前面5要措施,都不是今天要講的核心,其實第5條措施和今天說的有一些關聯,但是實現邏輯原理是不一樣的(不是今天的重點),說下第6條,對抗反編譯其實就是對抗反編譯工具,jadx丶jui都可以看程式碼,我發現有部分程式碼jui是編譯出錯的,這段程式碼在實際功能找中沒有任何作用,但是插入這段程式碼jui工具就會編譯出錯,這就和花指令是一個到了,無效的程式碼,給破解這帶來難度,插入這代花指令程式碼,一開始我使用入侵的形式(其實就是手動複製貼上),慢慢的核心方法越來越多,導致我閱讀自己的程式碼都開始費勁了,學習了AspectJ,可以完美解決這個問題,廢話不說開始

解決問題

  1. 當時我的方案是,通過ASM+Transformer庫來完成這種邏輯,其實這種邏輯是可以實現的,我也能完成,但是在對ASM對class,由於我在方法內部插入的程式碼過多,ASM的class的位元組碼過於複雜,總是出錯,開發成本非常高,上手難度很大,但是ASM庫非常強大,更加靈活
  2. AsepcJ來解決(今天的主角),學習成本低,上手簡單,完美解決問題

AspectJ的設計理念(概念)

Advice(通知)

注入到class檔案中的程式碼。典型的 Advice 型別有 before、after 和 around,分別表示在目標方法執行之前、執行後和完全替代目標方法執行的程式碼。 除了在方法中注入程式碼,也可能會對程式碼做其他修改,比如在一個class中增加欄位或者介面。

Joint point(連線點)

程式中可能作為程式碼注入目標的特定的點,例如一個方法呼叫或者方法入口。

Pointcut(切入點)

告訴程式碼注入工具,在何處注入一段特定程式碼的表示式。例如,在哪些 joint points 應用一個特定的 Advice。切入點可以選擇唯一一個,比如執行某一個方法,也可以有多個選擇,比如,標記了一個定義成@DebguTrace 的自定義註解的所有方法。

整合AspectJ

整合分為2種方法,建議外掛整合

外掛整合AspectJ

  1. 建立主專案app
  2. 建立library,AsepctJ
  3. 根目錄的build.gradle,插入 classpath ‘com.hujiang.aspectjx:gradle-android-plugin-aspectjx:2.0.4’
  4. AsepctJ的build.gradle,依賴 api ‘org.aspectj:aspectjrt:1.8.9’
  5. App主專案,依賴 implementation project(’:aspectj’) ,應用plugin外掛apply plugin: ‘com.hujiang.android-aspectjx’ 開源外掛地址講的很清楚,看下就會拉

gradle整合

來個簡單demo爽一下

在這裡插入圖片描述 app就是需要主專案,aspectj就是需要做插程式碼的library,看了上面的方式應該都會整合好了AspectJ

程式碼

public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        showMsg("我好牛B哦");
    }
    public void showMsg(String msg){
        Log.d("wyz", msg);
    }
}

AspectJ類

// 1:所需要插入程式碼的類,必須使用@Aspect註解
@Aspect
public class CoreAspetJ {
	// 需要注入的方法
    @After("call(* com.mmvoice.aspectjdemo.MainActivity.showMsg(java.lang.String))")
    public void showTaost(JoinPoint joinPoint) {
        Log.d("wyz", "AspectJ:牛B個錘子");
    }
}

執行效果

在這裡插入圖片描述 執行輸入了這2句,我的程式碼showMsg只打印一個Log的

總結

這一章節,主要講解了下整合方式,以及概念性的東西,以及我遇到的問題和解決問題的方式。