小試牛刀--Android AOP(面向切面編程)開(kāi)發(fā)

AOP面向切面編程開(kāi)發(fā)

說(shuō)明

定義

把某方面的功能提出來(lái)與一批對(duì)象進(jìn)行隔離,這樣與一批對(duì)象之間降低耦合性,就可以對(duì)某個(gè)功能進(jìn)行編程。

應(yīng)用
  • 用戶行為統(tǒng)計(jì)
  • 權(quán)限管理
  • 其他
AOP實(shí)現(xiàn)流程
  • aspectj 框架

是一個(gè)面向切面編程框架,它有專(zhuān)門(mén)的編譯器用來(lái)生成java 字節(jié) 碼,生成class文件。我們使用這個(gè)框架后編譯字節(jié)碼的工具不再試javac

下載aspectj 地址: http://www.eclipse.org/aspectj/downloads.php
下載aspectj的adt地址: http://www.eclipse.org/ajdt/downloads/#43zips
aspectJ 寫(xiě)法: http://fernandocejas.com/2014/08/03/aspect-oriented-programming-in-android/

  • 實(shí)現(xiàn)流程

    • 標(biāo)記切點(diǎn)

      用注解實(shí)現(xiàn)一個(gè)標(biāo)識(shí),添加到需要使用地方

    • 在切面中處理切點(diǎn)

      用AspectJ來(lái)實(shí)現(xiàn)切點(diǎn)的邏輯

    • 邏輯處理

  • 優(yōu)點(diǎn)
    因?yàn)橛昧俗约壕幾g器生成class文件,所以注解發(fā)生在編譯時(shí),對(duì)java性能無(wú)任何影響。

編碼實(shí)現(xiàn)

此處我們使用AOP實(shí)現(xiàn)方法耗時(shí)統(tǒng)計(jì)

Android studio添加AspectJ框架

  • 更改module的build 文件
//需要添加
import org.aspectj.bridge.IMessage
import org.aspectj.bridge.MessageHandler
import org.aspectj.tools.ajc.Main

apply plugin: 'com.android.application'

buildscript {
    repositories {
        mavenCentral()
    }
    //需要添加
    dependencies {
        classpath 'org.aspectj:aspectjtools:1.8.9'
        classpath 'org.aspectj:aspectjweaver:1.8.9'
    }
}
repositories {
    mavenCentral()
}
android {
    compileSdkVersion 26
    defaultConfig {
        applicationId "com.siqiyan.lightlu.aoptest"
        minSdkVersion 23
        targetSdkVersion 26
        versionCode 1
        versionName "1.0"

    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}
//需要添加
final def log = project.logger
final def variants = project.android.applicationVariants
variants.all { variant ->
    if (!variant.buildType.isDebuggable()) {
        log.debug("Skipping non-debuggable build type '${variant.buildType.name}'.")
        return;
    }

    JavaCompile javaCompile = variant.javaCompile
    javaCompile.doLast {
        String[] args = ["-showWeaveInfo",
                         "-1.8",
                         "-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;
            }
        }
    }
}

dependencies {
    implementation fileTree(include: ['*.jar'], dir: 'libs')
    implementation 'com.android.support:appcompat-v7:26.1.0'
    implementation 'com.android.support.constraint:constraint-layout:1.1.0'
    //需要添加
    compile files('libs/aspectjrt.jar')
    implementation files('libs/aspectjrt.jar')
}

  • 在module的libs目錄下導(dǎo)入aspectj.jar 文件


    image

創(chuàng)建注解類(lèi)



@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface BehaviorTimeTrace {
    String value();
}

添加標(biāo)記點(diǎn)(在需要處理的方法使用駐點(diǎn))

  • 使用注解前的代碼
/**
     * 語(yǔ)音的模塊
     *
     * @param view
     */
    public  void shake(View view)
    {
        long beagin=System.currentTimeMillis();

        //搖一搖的代碼邏輯
        
        SystemClock.sleep(3000);
        Log.i(TAG,"搖到一個(gè)妹子,距離500公里");
       

        Log.i(TAG,"消耗時(shí)間:  "+(System.currentTimeMillis()-beagin)+"ms");
    }

   /**
     * 搖一搖的模塊
     *
     * @param view
     */
  @BehaviorTimeTrace("搖一搖")
    public void shake(View view){
        SystemClock.sleep(3000);
        Log.i(TAG,"搖到一個(gè)妹子,距離500公里");
    }

AOP處理

具體處理思想分為下面幾步:

  • 1.獲取標(biāo)記點(diǎn)(獲取我們注解的方法)
  • 2.處理注解

詳細(xì)實(shí)現(xiàn):

  • 創(chuàng)建類(lèi)加上@Aspect注解,創(chuàng)建切面類(lèi)
    此次類(lèi)所有處理代碼如下
@Aspect
public class BehaviorTimeAspect {
    SimpleDateFormat format =new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    private static  final String TAG="AOPDemo";
    //比作切蛋糕,如何切蛋糕
    //第一步獲切點(diǎn),即獲得想要處理方法:* *代表所有方法,(..)代表所有參數(shù),這里可以根據(jù)具體的方法類(lèi)型來(lái)做處理
//    @Pointcut("execution(@com.siqiyan.lightlu.aoptest.BehaviorTimeTrace  * *(..))")
    @Pointcut("execution(@com.siqiyan.lightlu.aoptest.BehaviorTimeTrace  * *(..))")
    public void insertBehavior(){

    }

     //對(duì)于想好切的蛋糕,如何吃
    //第二步處理獲取的切點(diǎn)
    @Around("insertBehavior()")
    public Object dealPoint(ProceedingJoinPoint proceedingJoinPoint)throws Throwable{
        MethodSignature signature = (MethodSignature) proceedingJoinPoint.getSignature();
        //獲取標(biāo)記的方法
        BehaviorTimeTrace annotation = signature.getMethod().getAnnotation(BehaviorTimeTrace.class);
        //獲取標(biāo)記方法名
        String value = annotation.value();

        Log.i(TAG,value+"開(kāi)始使用的時(shí)間:   "+format.format(new Date()));
        long beagin=System.currentTimeMillis();
        Object proceed=null;

        try {
            //執(zhí)行方法
            proceed = proceedingJoinPoint.proceed();
        }catch (Exception e){

        }
        Log.i(TAG,"消耗時(shí)間:  "+(System.currentTimeMillis()-beagin)+"ms");

        return proceed;

    }


}
  • 獲取標(biāo)記點(diǎn)處理
    這個(gè)方法用來(lái)處理,到根據(jù)注解類(lèi)找到相應(yīng)的方法:獲得想要處理方法: * *代表所有方法,(..)代表所有參數(shù),這里可以根據(jù)具體的方法類(lèi)型來(lái)做處理
@Pointcut("execution(@com.siqiyan.lightlu.aoptest.BehaviorTimeTrace  * *(..))")
    public void insertBehavior(){

    }
  • 處理標(biāo)記點(diǎn)
//關(guān)聯(lián)上面的方法
  @Around("insertBehavior()")
    public Object dealPoint(ProceedingJoinPoint proceedingJoinPoint)throws Throwable{
    //固定寫(xiě)法,用于獲取標(biāo)記點(diǎn)
        MethodSignature signature = (MethodSignature) proceedingJoinPoint.getSignature();
        //獲取標(biāo)記的方法
        BehaviorTimeTrace annotation = signature.getMethod().getAnnotation(BehaviorTimeTrace.class);
        //獲取標(biāo)記方法名,即我們注解傳的參數(shù)
        String value = annotation.value();

        Log.i(TAG,value+"開(kāi)始使用的時(shí)間:   "+format.format(new Date()));
        long beagin=System.currentTimeMillis();
        Object proceed=null;

        try {
            //執(zhí)行我們注解的方法
            proceed = proceedingJoinPoint.proceed();
        }catch (Exception e){

        }
        Log.i(TAG,"消耗時(shí)間:  "+(System.currentTimeMillis()-beagin)+"ms");

        return proceed;

    }

效率

測(cè)試如下:


image

可以看到使用AspectJ 框架編譯時(shí)生成的字節(jié)碼,所以處理邏輯會(huì)占用更少的時(shí)間。查看編譯的源碼我們可以看到生成的class文件里面包含注解的處理。

Demo源碼

源碼 AOPTest

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 本章內(nèi)容: 面向切面編程的基本原理 通過(guò)POJO創(chuàng)建切面 使用@AspectJ注解 為AspectJ切面注入依賴(lài) ...
    謝隨安閱讀 3,436評(píng)論 0 9
  • WHY 如果說(shuō)OOP(面向?qū)ο蟮某绦蛟O(shè)計(jì))的主要思想是將問(wèn)題歸分到相應(yīng)的對(duì)象(類(lèi))中去實(shí)現(xiàn),再把相關(guān)類(lèi)模塊化使得模...
    野生大P閱讀 1,054評(píng)論 0 8
  • 一、簡(jiǎn)述 1、AOP的概念 如果你用java做過(guò)后臺(tái)開(kāi)發(fā),那么你一定知道AOP這個(gè)概念。如果不知道也無(wú)妨,套用百度...
    GitLqr閱讀 4,391評(píng)論 6 25
  • 昨天在花草論壇里看到有個(gè)花友問(wèn)大家為什么喜歡花的問(wèn)題,我回答:為了參與一顆生命的成長(zhǎng)。有花友笑話我說(shuō):養(yǎng)個(gè)花還養(yǎng)成...
    靜之般若閱讀 551評(píng)論 5 5
  • 一場(chǎng)突如其來(lái)的車(chē)禍,留下了女兒的身體和直子的靈魂。 平介面對(duì)擁有這直子靈魂的女兒,這扭曲了的關(guān)系,讓平介如何去應(yīng)對(duì)...
    theBugKiller閱讀 274評(píng)論 0 0

友情鏈接更多精彩內(nèi)容