AndroidStudio配置AspectJ環(huán)境實現(xiàn)AOP的方法

昨天看了一段android配置aspectj實現(xiàn)AOP的直播視頻,就試著自己配置了一下,可能是因為我自己的AndroidStudio環(huán)境的問題,碰到了不少的坑(其實還是因為對gradle理解的不多),但總歸是配置好了,就分享一下。

為懷遠(yuǎn)等地區(qū)用戶提供了全套網(wǎng)頁設(shè)計制作服務(wù),及懷遠(yuǎn)網(wǎng)站建設(shè)行業(yè)解決方案。主營業(yè)務(wù)為做網(wǎng)站、成都做網(wǎng)站、懷遠(yuǎn)網(wǎng)站設(shè)計,以傳統(tǒng)方式定制建設(shè)網(wǎng)站,并提供域名空間備案等一條龍服務(wù),秉承以專業(yè)、用心的態(tài)度為用戶提供真誠的服務(wù)。我們深信只要達(dá)到每一位用戶的要求,就會得到認(rèn)可,從而選擇與我們長期合作。這樣,我們也可以走得更遠(yuǎn)!

試了兩種方式,不過項目下的build.gradle,沒什么變化,直接看一下代碼吧:

build.gradle(項目下)

buildscript {
  ext {
    //android appcompat支持庫版本
    androidSupportVersion = '26.1.0'
    //編譯的 SDK 版本,如API20
    compileSdkVersion = 26
    //構(gòu)建工具的版本,其中包括了打包工具aapt、dx等,如API20對應(yīng)的build-tool的版本就是20.0.0
    buildToolsVersion = "26.0.2"
    //兼容的最低 SDK 版本
    minSdkVersion = 15
    //向前兼容,保存新舊兩種邏輯,并通過 if-else 方法來判斷執(zhí)行哪種邏輯
    targetSdkVersion = 26
    //kotlin版本號
    kotlin_version = '1.2.10'

    kotlinVersion = "org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version"
    appcompatV7 = "com.android.support:appcompat-v7:$androidSupportVersion"
    appcompatDesign = "com.android.support:design:$androidSupportVersion"
    constraintLayout = 'com.android.support.constraint:constraint-layout:1.0.2'
  }
  repositories {
    google()
    jcenter()
    mavenCentral()
  }
  dependencies {
    classpath 'com.android.tools.build:gradle:3.0.1'
    classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
    classpath 'org.greenrobot:greendao-gradle-plugin:3.2.1'
    // NOTE: Do not place your application dependencies here; they belong
    // in the individual module build.gradle files
    classpath 'org.aspectj:aspectjtools:1.8.13'
    classpath 'org.aspectj:aspectjweaver:1.8.13'
  }

}

allprojects {
  repositories {
    google()
    jcenter()
    mavenCentral()
  }
}

task clean(type: Delete) {
  delete rootProject.buildDir
}

看著一大堆,主要就是下面這幾行配置,其他的是我自己項目中用到的,根據(jù)自己需要配置就行。

buildscript {
  repositories {
    mavenCentral()
  }
  dependencies {
    classpath 'org.aspectj:aspectjtools:1.8.13'
    classpath 'org.aspectj:aspectjweaver:1.8.13'
  }
}

repositories {
  mavenCentral()
}

其實這幾行配置在app的build.gradle里也是可以的,但是因為項目下的build.gradle里已經(jīng)有buildscript {}、allprojects {repositories{} },就配置在這里了。

然后有兩種配置方式:

第一種

只有一個主Module app的情況下,配置app的build.gradle:

apply plugin: 'com.android.application'

apply plugin: 'kotlin-android'

apply plugin: 'kotlin-android-extensions'

apply plugin: 'org.greenrobot.greendao'

android {
  compileSdkVersion rootProject.ext.compileSdkVersion
  buildToolsVersion rootProject.ext.buildToolsVersion
  defaultConfig {
    applicationId "填入自己的applicationId"
    minSdkVersion rootProject.ext.minSdkVersion
    targetSdkVersion rootProject.ext.targetSdkVersion
    versionCode 1
    versionName "1.0"
    //Lambda配置
//    jackOptions.enabled = true
//    android.compileOptions.sourceCompatibility 1.8
    buildConfigField "boolean", "LOG", "true"http:// 顯示Log
    testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    //支持矢量圖
    vectorDrawables.useSupportLibrary = true
    ndk {
      //選擇要添加的對應(yīng)cpu類型的.so庫。
      abiFilters 'armeabi', 'armeabi-v7a', 'arm64-v8a', 'x86', 'x86_64', 'mips', 'mips64'
    }
  }

  buildTypes {
    release {
      minifyEnabled false
      buildConfigField "boolean", "LOG", "false"http:// 顯示Log
      proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
    }


  }

  //Lambda配置
  compileOptions {
    sourceCompatibility JavaVersion.VERSION_1_8
    targetCompatibility JavaVersion.VERSION_1_8
  }

  dataBinding {
    enabled true
  }

  greendao {
    schemaVersion 1//數(shù)據(jù)庫版本號
    daoPackage 'com.test.qby.newtestapplication.greendao'//設(shè)置DaoMaster、DaoSession、Dao包名
    targetGenDir 'src/main/java'//設(shè)置DaoMaster、DaoSession、Dao目錄
    //targetGenDirTest:設(shè)置生成單元測試目錄
    //generateTests:設(shè)置自動生成單元測試用例
  }

  lintOptions {
    abortOnError true
  }

}


dependencies {
  implementation fileTree(include: ['*.jar'], dir: 'libs')
  implementation rootProject.ext.kotlinVersion
  implementation rootProject.ext.appcompatV7
  implementation rootProject.ext.constraintLayout
  compile rootProject.ext.appcompatDesign
  testImplementation 'junit:junit:4.12'
  androidTestImplementation 'com.android.support.test:runner:1.0.1'
  androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1'
  compile 'jp.wasabeef:glide-transformations:3.0.1'
  // If you want to use the GPU Filters
  compile 'jp.co.cyberagent.android.gpuimage:gpuimage-library:1.4.1'
  //騰訊bugly
  compile 'com.tencent.bugly:crashreport:latest.release'
  compile 'com.tencent.bugly:nativecrashreport:latest.release'
  //retrofit
  compile 'com.squareup.retrofit2:retrofit:2.3.0'
  compile 'com.squareup.retrofit2:converter-gson:2.3.0'
  compile 'com.squareup.retrofit2:adapter-rxjava2:2.3.0'
  compile 'com.squareup.okhttp3:logging-interceptor:3.9.0'
  //rxJava
  compile 'io.reactivex.rxjava2:rxandroid:2.0.1'
  // Because RxAndroid releases are few and far between, it is recommended you also
  // explicitly depend on RxJava's latest version for bug fixes and new features.
  compile 'io.reactivex.rxjava2:rxjava:2.1.8'
  //greenDao
  compile 'org.greenrobot:greendao:3.2.0'
  //換膚功能
  compile 'com.zhy:changeskin:4.0.2'
  //AOP面向切面編程,加入這行就不用在libs下引入jar包了,不然要寫成compile file(libs/aspectjrt.jar)
  compile 'org.aspectj:aspectjrt:1.8.13'
}
/*
//在項目下配置了,此處就不需要了
buildscript {
  repositories {
    mavenCentral()
  }
  dependencies {
    classpath 'org.aspectj:aspectjtools:1.8.13'
    classpath 'org.aspectj:aspectjweaver:1.8.13'
  }
}

repositories {
  mavenCentral()
}
*/

import org.aspectj.bridge.IMessage
import org.aspectj.bridge.MessageHandler
import org.aspectj.tools.ajc.Main

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.5",
             "-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
      }
    }
  }
}

這一個gradle主要的東西就是這些:

//AOP面向切面編程,加入這行就不用在libs下引入jar包了,不然要寫成compile file(libs/aspectjrt.jar)
compile 'org.aspectj:aspectjrt:1.8.13'

import org.aspectj.bridge.IMessage
import org.aspectj.bridge.MessageHandler
import org.aspectj.tools.ajc.Main

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.5",
             "-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
      }
    }
  }
}

下面那一堆是用命令在編譯最后做一些關(guān)聯(lián)的,具體的我也不懂,只管加上好了。

第二種

有多個module都需要用到aspectj,特別是組件開發(fā)的情況下,不可能每個module都配置一下,所以就需要新建一個aspectj的module作為項目的library。

app下build.gradle需要修改:

//AOP面向切面編程,加入這行就不用在libs下引入jar包了,不然要寫成compile file(libs/aspectjrt.jar)
compile 'org.aspectj:aspectjrt:1.8.13'

去掉,改為

implementation project(':aspectjlib')

不過上面這句在你添加module依賴的時候會自動生成。

新建library的build.gradle配置如下:

apply plugin: 'com.android.library'

android {
  compileSdkVersion rootProject.ext.compileSdkVersion
  buildToolsVersion rootProject.ext.buildToolsVersion
  defaultConfig {
    minSdkVersion rootProject.ext.minSdkVersion
    targetSdkVersion rootProject.ext.targetSdkVersion
    versionCode 1
    versionName "1.0"

    testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"

  }

  buildTypes {
    release {
      minifyEnabled false
      proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
    }
  }

}

dependencies {
  implementation fileTree(dir: 'libs', include: ['*.jar'])

  implementation rootProject.ext.appcompatV7
  testImplementation 'junit:junit:4.12'
  androidTestImplementation 'com.android.support.test:runner:1.0.1'
  androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1'
  //AOP
  compile 'org.aspectj:aspectjrt:1.8.13'
}

import org.aspectj.bridge.IMessage
import org.aspectj.bridge.MessageHandler
import org.aspectj.tools.ajc.Main

android.libraryVariants.all { variant ->
  JavaCompile javaCompile = variant.javaCompile
  javaCompile.doLast {
    String[] args = ["-showWeaveInfo",
             "-1.5",
             "-inpath", javaCompile.destinationDir.toString(),
             "-aspectpath", javaCompile.classpath.asPath,
             "-d", javaCompile.destinationDir.toString(),
             "-classpath", javaCompile.classpath.asPath,
             "-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的gradle中的稍微有點區(qū)別,一個是module,一個是library,gradle中的東西不一樣。

兩種配置方式基本就是這樣了,使用方法我也是剛了解一點,記錄一下簡單的計算性能的用法吧

自定義注解類:

package com.test.qby.aspectjlib.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * Created by qby on 2018/1/26 0026.
 * 自定義注解
 */
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface IFirstAnnotation {
  String value();
}

@Target 注解目標(biāo),表示注解使用在什么地方,這里是METHOD方法;@Retention 保留策略,表示注解調(diào)用時機(jī),這里RUNTIME運行時

切面類

import android.widget.Toast;
import com.test.qby.aspectjlib.annotation.IFirstAnnotation;
import com.test.qby.newtestapplication.app.MyApplication;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import java.lang.reflect.Method;
import java.lang.reflect.TypeVariable;
import java.util.Locale;

/**
 * Created by qby on 2018/1/26 0026.
 * 自定義注解行為
 */
@Aspect
public class MethodBehaviorAspect {
  private static final String TAG = "aspect_aby";

  @Pointcut("execution(@com.test.qby.aspectjlib.annotation.IFirstAnnotation * *(..))")
  public void firstMethodAnnotationBehavior() {
  }

  @Pointcut("execution(* com.test.qby.newtestapplication.ui.MainActivity.aspectClick(android.view.View))")
  public void secondMethodAnnotationBehavior() {
  }

  @Around("firstMethodAnnotationBehavior()")
  public Object wavePointcutAround(ProceedingJoinPoint joinPoint) throws Throwable {

    MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
    // 類名
    String className = methodSignature.getDeclaringType().getSimpleName();
    // 方法名
    String methodName = methodSignature.getName();
    // 功能名
    IFirstAnnotation behaviorTrace = methodSignature.getMethod()
        .getAnnotation(IFirstAnnotation.class);
    String value = behaviorTrace.value();
//    String value = "點擊";
    long start = System.currentTimeMillis();
    Object result = joinPoint.proceed();
    long duration = System.currentTimeMillis() - start;
    Log.e(TAG, String.format("%s類中%s方法執(zhí)行%s功能,耗時:%dms", className, methodName, value, duration));
    Toast.makeText(MyApplication.getContext(), String.format(Locale.CHINESE, "%s類中%s方法執(zhí)行%s功能,耗時:%dms", className, methodName, value, duration), Toast.LENGTH_SHORT).show();
    return result;
  }
}

@Aspect指定切面類;@Pointcut切入點;@Around是切入方式Advice的一種,表示在切入點前后插入代碼,還有@Before、@After;Pointcut語法,execution,表示根據(jù)Advice在執(zhí)行方法內(nèi)部代碼前后插入代碼,call,表示根據(jù)Advice在調(diào)用方法前后插入代碼......

頁面調(diào)用

@IFirstAnnotation("測試Aspect")
public void aspectClick(View view) {
   try {
     Thread.sleep(new Random().nextInt(1000));
   } catch (InterruptedException e) {
     e.printStackTrace();
   }
 }

@IFirstAnnotation調(diào)用注解,()內(nèi)部為在IFirstAnnotation中寫的value的值,去掉value()后此處去掉()

注意:在MethodBehaviorAspect 類中如果有用到Context,可直接使用joinPoint.getTarget()類型轉(zhuǎn)換成Context,這里是由于項目使用了databinding,部分getTarget()獲取到的值不能強(qiáng)轉(zhuǎn)為Context,所以這里用的MyApplication獲取的Context

這只是個人的初步嘗試,里面當(dāng)然還有很多內(nèi)容需要去學(xué),剛看了CSDN上有人寫的幾篇關(guān)于AOP的內(nèi)容,都挺詳細(xì)的,給出其中一個地址,自己看吧:https://www.jb51.net/article/110560.htm

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持創(chuàng)新互聯(lián)。

當(dāng)前文章:AndroidStudio配置AspectJ環(huán)境實現(xiàn)AOP的方法
URL分享:http://muchs.cn/article38/ihdjsp.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供定制開發(fā)、電子商務(wù)、面包屑導(dǎo)航、建站公司關(guān)鍵詞優(yōu)化、商城網(wǎng)站

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)

微信小程序開發(fā)