1. 程式人生 > >面向切面程式設計在android中的應用(Aspect Oriented Programming in android)

面向切面程式設計在android中的應用(Aspect Oriented Programming in android)

面向切面程式設計在android中的應用

Aspect Oriented Programming in android project

背景

在我們實際的Android專案開發中經常碰到的一個問題就是Token過期的處理問題
客戶端的很多介面都要依賴Token,對Token過期處理不當就必定會為專案埋下很多坑,所以這就促使我們必需要找找到一個有效可行的方式來處理Token過期問題。
但是在使用新方式來處理Token過期問題時我們又想在不改動一丁點兒(或者改動儘可能小)專案已有原始碼的情況下(以免對專案做大換血導致意外bug的滋生)來植入我們對Token的處理(或是其他)邏輯程式碼。那這應該怎麼辦呢?有沒有辦法呢?

————辦法還是有的

下面我們就來介紹下在實際專案中是怎麼和如何以及使用什麼方法來有效的對Token過期進行處理的。
在進入Iseema實際專案的介紹前,我們有必要先來簡單認識下AOP(Aspect Oriented Programming)AspectJ是什麼以及在如何在一個Android專案中使用AOP。

什麼是AOP?(來自網路,一搜一大把)

AOP為Aspect Oriented Programming的縮寫,意為:面向切面程式設計,通過預編譯方式和執行期動態代理實現程式功能的統一維護的一種技術。AOP是OOP的延續,是軟體開發中的一個熱點。利用AOP可以對業務邏輯的各個部分進行隔離,從而使得業務邏輯各部分之間的耦合度降低,提高程式的可重用性,同時提高了開發的效率。

從上面的定義可以看出,利用AOP可以對業務邏輯的各個部分進行隔離,從而使得業務邏輯各部分之間的耦合度降低。這正好符合我們在不改動現有程式碼以低耦合的方式向原有程式碼中織入程式碼的目的。

AOP中的一些概念 (來自網路,一搜一大把)

1、橫切關注點
對哪些方法進行攔截,攔截後怎麼處理,這些關注點稱之為橫切關注點
2、切面(aspect)
類是對物體特徵的抽象,切面就是對橫切關注點的抽象
3、連線點(joinpoint)
被攔截到的點,指的就是被攔截到的方法,實際上連線點還可以是欄位或者構造器
4、切入點(pointcut)
對連線點進行攔截的定義
5、通知(advice)
所謂通知指的就是指攔截到連線點之後要執行的程式碼,通知分為前置、後置、異常、最終、環繞通知五類
6、目標物件
代理的目標物件
7、織入(weave)
將切面應用到目標物件並導致代理物件建立的過程
8、引入(introduction)
在不修改程式碼的前提下,引入可以在執行期為類動態地新增一些方法或欄位

什麼是AspectJ?

如何在Android中使用AspectJ?

如何在Android專案中使用呢?根據各種搜尋和研究發現最終發現,我們只需要按照以下幾個步驟(主要參考了 Jake Wharton的Hugo Library開源專案的實現)就可以很輕鬆的將AspectJ整合到我們的Android專案中。這裡主使用AspectJ版本是1.8.13,其他的版本應該也遵循同樣的步驟。

專案根目錄下的build.gradle檔案中配置aspectjtools

在下面的dependencies block中加入一句classpath 'org.aspectj:aspectjtools:1.8.13'即可新增對aspectjtools的依賴。aspectjtools是在Android上使用AspectJ的外掛,主要用於編輯位元組碼在位元組碼中植入通知

buildscript {
    repositories {
        jcenter()
        google()
    }
    dependencies {
        ......
        // 引入aspectjtools
        classpath 'org.aspectj:aspectjtools:1.8.13'
        ......
    }
}

allprojects {
    repositories {
        jcenter()
        google()
}

app model下面的build.gradle檔案中配置aspectjrt

1)、在下面的dependencies block中加入一句:compile 'org.aspectj:aspectjrt:1.8.13'新增對aspectjrt依賴的依賴,aspectjrt是AspectJ的執行時環境,所必須要引入。
2)、在西面的android block和dependencies block之間新增如下程式碼:

   android.applicationVariants.all { variant ->
    JavaCompile javaCompile = variant.javaCompile
    javaCompile << {
        String[] args = ["-showWeaveInfo",
                         "-1.8",
                         "-XnoInline",
                         "-inpath", javaCompile.destinationDir.toString(),
                         "-aspectpath", javaCompile.classpath.asPath,
                         "-d", javaCompile.destinationDir.toString(),
                         "-classpath", javaCompile.classpath.asPath,
                         "-log", "weave.log",
                         "-bootclasspath", android.bootClasspath.join(File.pathSeparator)
        ]

        MessageHandler handler = new MessageHandler(true)
        new Main().run(args, handler)

        def log = project.logger
        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:
                case IMessage.INFO:
                    log.info message.message, message.thrown
                    break
                case IMessage.DEBUG:
                    log.debug message.message, message.thrown
                    break
            }
        }
}

app model下的build.gradle與AspecJ配置相關的完整配置

注意下面倒入的包,別倒錯了

import groovy.xml.XmlUtil
import org.aspectj.bridge.IMessage
import org.aspectj.bridge.MessageHandler
import org.aspectj.tools.ajc.Main

apply plugin: 'com.android.application'

android {
    ......
    ......
}
// 對編譯後的位元組碼做處理,新增面向切面(AOP)的程式設計支援
android.applicationVariants.all { variant ->
    JavaCompile javaCompile = variant.javaCompile
    javaCompile << {
        String[] args = ["-showWeaveInfo",
                         "-1.8",
                         "-XnoInline",
                         "-inpath", javaCompile.destinationDir.toString(),
                         "-aspectpath", javaCompile.classpath.asPath,
                         "-d", javaCompile.destinationDir.toString(),
                         "-classpath", javaCompile.classpath.asPath,
                         "-log", "weave.log",
                         "-bootclasspath", android.bootClasspath.join(File.pathSeparator)
        ]

        MessageHandler handler = new MessageHandler(true)
        new Main().run(args, handler)

        def log = project.logger
        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:
                case IMessage.INFO:
                    log.info message.message, message.thrown
                    break
                case IMessage.DEBUG:
                    log.debug message.message, message.thrown
                    break
            }
        }
}

dependencies {
    ......
   // 新增aspectjrt的依賴
   compile 'org.aspectj:aspectjrt:1.8.13'
    ......
}

到此,一個Android專案已經集成了AspectJ

在進入Iseema實際專案前,讓我們先來看一個更簡單的具體使用AspectJ的例子,以便驗證我們是否成功集成了以及簡單瞭解下AspectJ的使用。

舉個栗子
假設我們目前有一個應用App類,需要呼叫業務類OrderManager完成一些業務,OrderManager包含了與訂操作單相關API,這些API都要求使用者登陸後才有許可權訪問。
OrderManager類如下:

/**
 * @author AveryZhong.
 */

public class OrderManger {
    private static final String TAG = OrderManger.class.getSimpleName();
    
    // 建立訂單
    public String createOrder(String productName) {
        return "Create " + productName + " order success";
    }
    
    // 查詢訂單
    public String queryOrder(String productName) {
        return "Query " + productName + " order success";
    }
    
    // 刪除訂單
    public String deleteOrder(String productName) {
        return "Delete " + productName + " order success";
    }

}

在沒有使用AspectJ的情況下App類畫風通常是這樣的:

/**
 * @author AveryZhong.
 */

public class App {
    private static final String TAG = App.class.getSimpleName();
    
    // 注入OrderManger
    @Inject
    private OrderManger mOrderManger;
    
    // 處理訂單的建立
    public void processOrderCreation() {
        if (!isLogined()) { // 使用者未登陸,則跳轉到登陸頁面
            jumpToLoginPage();
        } else { // 使用者已登陸,則可進行訂單的建立操作
            String result = mOrderManger.createOrder("productName");
            Log.d(TAG, "processOrderCreation: " + result);
        }
    }

    // 處理訂單的刪除
    public void processOrderDeletion() {
        if (!isLogined()) {  // 使用者未登陸,則跳轉到登陸頁面
            jumpToLoginPage();
        } else { // 使用者已登陸,則可進行訂單的刪除操作
            String result = mOrderManger.deleteOrder("productName");
            Log.d(TAG, "processOrderDeletion: " + result);
        }
    }

    // 查詢訂單
    public void queryOrder() {
        if (!isLogined()) {  // 使用者未登陸,則跳轉到登陸頁面
            jumpToLoginPage();
        } else { // 使用者已登陸,則可進行訂單的查詢操作
            String result = mOrderManger.queryOrder("productName");
            Log.d(TAG, "queryOrder: " + result);
        }
    }
     // 此處省略好多方法......

}

觀察上面的App類會發現,在呼叫每個OrderManager類方法的時候都需要做使用者是否登陸的判斷,因為這些操作必須在使用者登陸後才有許可權操作。這樣的判斷充斥在整個App類中,是登陸業務僅僅的耦合在了訂單業務中。

在使用AspectJ的情況下App類畫風通常是這樣的:

/**
 * @author AveryZhong.
 */

public class App {
    private static final String TAG = App.class.getSimpleName();
    
    // 注入OrderManger
    @Inject
    private OrderManger mOrderManger;
    
    // 處理訂單的建立
    public void processOrderCreation() {
         String result = mOrderManger.createOrder("productName");
         Log.d(TAG, "processOrderCreation: " + result);
    }

    // 處理訂單的刪除
    public void processOrderDeletion() {
         String result = mOrderManger.deleteOrder("productName");
         Log.d(TAG, "processOrderDeletion: " + result);
    }

    // 查詢訂單
    public void queryOrder() {
         String result = mOrderManger.queryOrder("productName");
         Log.d(TAG, "queryOrder: " + 
            
           

相關推薦

面向切面程式設計android應用Aspect Oriented Programming in android

面向切面程式設計在android中的應用Aspect Oriented Programming in android project背景在我們實際的Android專案開發中經常碰到的一個問題就是Token過期的處理問題。客戶端的很多介面都要依賴Token,對Token過期處理

Spring框架學習筆記——IoCInversion of Control,控制反轉和AOPAspect Oriented Programming面向切面程式設計

1、Spring IoC IoC是一個Bean容器,在Spring中,它認為一切Java資源都是Java Bean,容器的目標就是管理這些Bean和它們之間的關係。所以在Spring IoC裡面裝載的各種Bean,也可以理解為Java的各種資源,包括Java Bean的建立、事件、行為和Java

AOP面向切面程式設計思想的原理簡單理解

閱讀本文章的前提:java基礎,具備java面向物件思想 深入學習需要了解知識點:jdk 靜態代理,動態代理,java繼承,多型,介面 AOP:面向切面程式設計思想是繼OOP面向物件程式設計思想後,又一個偉大思想。當你意識到這句話的時候,你大概已經理解了什麼是AOP;

javascript面向物件程式設計--惰性例項化實現按需例項化

javascript是以物件為基礎,以函式為模型,以原型為繼承機制的開發模式 惰性例項化:避免在頁面中使用javascript初始化執行時就例項化類,而是將一些類的例項化推遲到需要時候才去例項化,避免資源過早的消耗 var myNamespace=function(){   &

山東理工大學ACM平臺題答案 面向物件程式設計上機練習三有預設引數的函式

#include <stdio.h> int max(int a, int b, int c = 0) {       int r = a;       if (b > r) r

山東理工大學ACM平臺題答案 面向物件程式設計上機練習三有預設引數的函式1142

               面向物件程式設計上機練習三(有預設引數的函式) Time Limit: 1000ms   Memory limit: 65536K  有疑問?點這裡^_^ 題目描述   

sdut 面向物件程式設計上機練習三有預設引數的函式

  面向物件程式設計上機練習三(有預設引數的函式) Time Limit: 1000MS Memory limit: 65536K 題目描述 利用預設引數的函式實現求2個或3個整數的最大

【含有預設引數的函式】面向物件程式設計上機練習三有預設引數的函式

Think: 1、學習理解: (1):若在定義時而不是在宣告時置預設值,那麼函式定義一定要在函式的呼叫之前 (2):不能將實際值傳遞給引用型別的引數。可以將變數作引用型別引數的預設值,這時變數必須是已經宣告且是全域性變數。 (3):若給某一引數設定了預設

javaScript設計模式之面向對象編程object-oriented programming,OOP(一)

email 全局變量 color javascrip 原型 obj 只有一個 沒有 ted 面試的時候,總會被問到,你對javascript面向對象的理解? 面向對象編程(object-oriented programming,OOP)是一種程序設計範型。它講對象

javaScript設計模式之面向對象編程object-oriented programming,OOP(二

ogr 調用 抽象 組合 copy object 每次 prototype 種類型 接上一篇 面向對象編程的理解? 答:面向對象編程,就是將你的需求抽象成一個對象,然後針對這個對象分析其特征(屬性)與動作(方法)。這個對象我們稱之為類。面向對象編程思想其中一個特點就是封

PHP記錄之面向物件Object-oriented programming,OOP瞭解下唄

在面向物件的程式設計(英語:Object-oriented programming,縮寫:OOP)中,物件是一個由資訊及對資訊進行處理的描述所組成的整體,是對現實世界的抽象,然而在現實世界裡我們所面對的事情都是物件,如計算機、電視機、自行車等,我們來看下物件的三個主要特徵:

C# 使用面向切面程式設計AOP實踐程式碼整潔

1. 前言 最近在看《架構整潔之道》一書,書中反覆提到了面向物件程式設計的 SOLID 原則(在作者的前一本書《程式碼整潔之道》也是被大力闡釋),而面向切面程式設計(Aop)作為面向物件程式設計的有力補充,對實踐整潔程式碼更是如虎添翼。 1. Aop 是什麼? 在討論 Aop 之前,我們可以先看看一段很常見

AspectJ教程--AOP面向切面程式設計框架Android

AOP的概念很久前就接觸過了,不過沒有真正寫過專案,甚至Demo都沒有,今天把這點缺陷補上。 推薦兩篇文章(本文部分圖片引自這兩篇文章): 1. 【翻譯】Android中的AOP程式設計 2. 【深入理解Android之AOP】

在idea利用Spring進行面向切面程式設計AOP的一個例子

(1)在idea中新建立一個maven專案aopAspectj,,編寫POM檔案,匯入jar包: <dependencies> <!--aspectj依賴--> <dependency> <grou

【小家java】POP面向過程程式設計、OOP面向物件程式設計、AOP面向切面程式設計三種程式設計思想的區別和聯絡

相關閱讀 【小家java】java5新特性(簡述十大新特性) 重要一躍 【小家java】java6新特性(簡述十大新特性) 雞肋升級 【小家java】java7新特性(簡述八大新特性) 不溫不火 【小家java】java8新特性(簡述十大新特性) 飽受讚譽 【小家java】java9

02 Spring的AOP面向切面程式設計

1、關於AOP AOP(Aspect Oriented Programming),即面向切面程式設計,可以說是OOP(Object Oriented Programming,面向物件程式設計)的補充和完善。OOP引入封裝、繼承、多型等概念來建立一種物件層次結構,用於模擬公共行為的一個集合。O

詳解Spring面向切面程式設計AOP)三種實現

一、什麼是AOP AOP(Aspect Oriented Programming),即面向切面程式設計,可以說是OOP(Object Oriented Programming,面向物件程式設計)的補充和完善。OOP引入封裝、繼承、多型等概念來建立一種物件層次結構,用於模擬公共行為的一個集合。不過OOP允許開

spring面試題面向切面程式設計AOP+MVC

Spring面向切面程式設計(AOP) 1.  解釋AOP 面向切面的程式設計,或AOP, 是一種程式設計技術,允許程式模組化橫向切割關注點,或橫切典型的責任劃分,如日誌和事務管理。   2. Aspect 切面 AOP

面試題: 面向切面程式設計AOP的理解

AOP是什麼?     AOP的全稱是Aspect Orient Programming,即面向切面程式設計。是對OOP(Object Orient Programming)的一種補充,戰門用於處理一些具有橫切性質的服務。常常用於日誌輸出、安全控制等。

Spring2AOP 面向切面程式設計AOP目錄

Spring Core: Spring的核心功能即IOC容器,解決物件的建立及物件之間的依賴關係 Spring WEB: Spring對WEB模組的支援 Spring AOP: 面向切面程式設計 AOP的概述 AOP的底層實現 Spring AOP開發