SoFunction
Updated on 2025-03-04

AndroidStudio Configure AspectJ environment to implement AOP

Yesterday I watched a live video of Android configuration aspectj implementing AOP, so I tried to configure it myself. Maybe it was because of my own Android Studio environment and I encountered a lot of pitfalls (actually because I don’t understand much about gradle), but I have configured it all, so I will share it.

I tried two methods, but there was no change in the project. Just look at the code:

(Page 2)

buildscript {
  ext {
    //android appcompat support library version    androidSupportVersion = '26.1.0'
    //Compiled SDK versions, such as API20    compileSdkVersion = 26
    //The build tool version includes packaging tools aapt, dx, etc. For example, the build-tool version corresponding to API20 is 20.0.0    buildToolsVersion = "26.0.2"
    //The minimum SDK version compatible    minSdkVersion = 15
    //Forward compatibility, save the old and new logic, and use the if-else method to determine which logic to execute    targetSdkVersion = 26
    //kotlin version number    kotlin_version = '1.2.10'

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

}

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

task clean(type: Delete) {
  delete 
}

Looking at a lot of them, the main ones are the following lines of configuration, and the others are used in my own project, just configure them according to my needs.

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

repositories {
  mavenCentral()
}

In fact, these lines are also OK to configure in the app, but because there are already buildscript {} and allprojects {repositories{}} in the project, it is configured here.

Then there are two configuration methods:

The first type

If there is only one main Module app, configure the app:

apply plugin: ''

apply plugin: 'kotlin-android'

apply plugin: 'kotlin-android-extensions'

apply plugin: ''

android {
  compileSdkVersion 
  buildToolsVersion 
  defaultConfig {
    applicationId "Fill in your own applicationId"
    minSdkVersion 
    targetSdkVersion 
    versionCode 1
    versionName "1.0"
    //Lambda configuration//     = true
//     1.8
    buildConfigField "boolean", "LOG", "true"// Show Log    testInstrumentationRunner ""
    //Support vector diagram     = true
    ndk {
      //Select the .so library of the corresponding CPU type to be added.      abiFilters 'armeabi', 'armeabi-v7a', 'arm64-v8a', 'x86', 'x86_64', 'mips', 'mips64'
    }
  }

  buildTypes {
    release {
      minifyEnabled false
      buildConfigField "boolean", "LOG", "false"// Show Log      proguardFiles getDefaultProguardFile(''), ''
    }


  }

  //Lambda configuration  compileOptions {
    sourceCompatibility JavaVersion.VERSION_1_8
    targetCompatibility JavaVersion.VERSION_1_8
  }

  dataBinding {
    enabled true
  }

  greendao {
    schemaVersion 1//Database version number    daoPackage ''//Set DaoMaster, DaoSession, Dao package name    targetGenDir 'src/main/java'//Set DaoMaster, DaoSession, Dao Directory    //targetGenDirTest: Set the generated unit test directory    //generateTests: Set up automatic generation of unit test cases  }

  lintOptions {
    abortOnError true
  }

}


dependencies {
  implementation fileTree(include: ['*.jar'], dir: 'libs')
  implementation 
  implementation .appcompatV7
  implementation 
  compile 
  testImplementation 'junit:junit:4.12'
  androidTestImplementation ':runner:1.0.1'
  androidTestImplementation ':espresso-core:3.0.1'
  compile ':glide-transformations:3.0.1'
  // If you want to use the GPU Filters
  compile ':gpuimage-library:1.4.1'
  //Tencent bugly  compile ':crashreport:'
  compile ':nativecrashreport:'
  //retrofit
  compile '.retrofit2:retrofit:2.3.0'
  compile '.retrofit2:converter-gson:2.3.0'
  compile '.retrofit2:adapter-rxjava2:2.3.0'
  compile '.okhttp3:logging-interceptor:3.9.0'
  //rxJava
  compile '.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 '.rxjava2:rxjava:2.1.8'
  //greenDao
  compile ':greendao:3.2.0'
  //Skin Removal Function  compile ':changeskin:4.0.2'
  //AOP is oriented to tangent programming. If you add this line, you don’t need to introduce jar package under libs, otherwise you have to write it as compile file(libs/)  compile ':aspectjrt:1.8.13'
}
/*
 //Configuration under the project, no need here
 buildscript {
   repositories {
     mavenCentral()
   }
   dependencies {
     classpath ':aspectjtools:1.8.13'
     classpath ':aspectjweaver:1.8.13'
   }
 }

 repositories {
   mavenCentral()
 }
 */

import 
import 
import 

final def log = 
final def variants = 

 { variant ->
  if (!()) {
    ("Skipping non-debuggable build type '${}'.")
    return
  }

  JavaCompile javaCompile = 
   {
    String[] args = ["-showWeaveInfo",
             "-1.5",
             "-inpath", (),
             "-aspectpath", ,
             "-d", (),
             "-classpath", ,
             "-bootclasspath", ()]
     "ajc args: " + (args)

    MessageHandler handler = new MessageHandler(true)
    new Main().run(args, handler)
    for (IMessage message : (null, true)) {
      switch (()) {
        case :
        case :
        case :
           , 
          break
        case :
           , 
          break
        case :
           , 
          break
        case :
           , 
          break
      }
    }
  }
}

The main things about this gradle are these:

//AOP is oriented to tangent programming. If you add this line, you don’t need to introduce jar package under libs, otherwise you have to write it as compile file(libs/)compile ':aspectjrt:1.8.13'

import 
import 
import 

final def log = 
final def variants = 

 { variant ->
  if (!()) {
    ("Skipping non-debuggable build type '${}'.")
    return
  }

  JavaCompile javaCompile = 
   {
    String[] args = ["-showWeaveInfo",
             "-1.5",
             "-inpath", (),
             "-aspectpath", ,
             "-d", (),
             "-classpath", ,
             "-bootclasspath", ()]
     "ajc args: " + (args)

    MessageHandler handler = new MessageHandler(true)
    new Main().run(args, handler)
    for (IMessage message : (null, true)) {
      switch (()) {
        case :
        case :
        case :
           , 
          break
        case :
           , 
          break
        case :
           , 
          break
        case :
           , 
          break
      }
    }
  }
}

The following group of people use commands to make some correlation at the end of compilation. I don’t understand the specific ones, just add them.

The second type

There are multiple modules that require aspectj. Especially when component development is developed, it is impossible to configure each module, so you need to create a new aspectj module as the project library.

Need to modify under the app:

Will

//AOP is oriented to tangent programming. If you add this line, you don’t need to introduce jar package under libs, otherwise you have to write it as compile file(libs/)compile ':aspectjrt:1.8.13'

Remove and change to

implementation project(':aspectjlib')

However, the above sentence will be automatically generated when you add module dependencies.

The configuration of the new library is as follows:

apply plugin: ''

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

    testInstrumentationRunner ""

  }

  buildTypes {
    release {
      minifyEnabled false
      proguardFiles getDefaultProguardFile(''), ''
    }
  }

}

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

  implementation .appcompatV7
  testImplementation 'junit:junit:4.12'
  androidTestImplementation ':runner:1.0.1'
  androidTestImplementation ':espresso-core:3.0.1'
  //AOP
  compile ':aspectjrt:1.8.13'
}

import 
import 
import 

 { variant ->
  JavaCompile javaCompile = 
   {
    String[] args = ["-showWeaveInfo",
             "-1.5",
             "-inpath", (),
             "-aspectpath", ,
             "-d", (),
             "-classpath", ,
             "-bootclasspath", (
        )]

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

    def log = 
    for (IMessage message : (null, true)) {
      switch (()) {
        case :
        case :
        case :
           , 
          break
        case :
        case :
           , 
          break
        case :
           , 
          break
      }
    }
  }
}

Note: The following bunch is slightly different from the ones in the app's gradle. One is module and the other is library. The things in gradle are different.

This is basically the case with the two configuration methods. I just learned a little about how to use it. Let’s record the usage of simple computing performance.

Custom annotation class:

package ;
import ;
import ;
import ;
import ;

/**
  * Created by qby on 2018/1/26 0026.
  * Custom annotations
  */
@Target()
@Retention()
public @interface IFirstAnnotation {
  String value();
}

@Target annotation target, indicating where the annotation is used, here is the METHOD method; @Retention policy, indicating the annotation call time, here is the RUNTIME runtime

Face-cut

import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;

/**
  * Created by qby on 2018/1/26 0026.
  * Custom annotation behavior
  */
@Aspect
public class MethodBehaviorAspect {
  private static final String TAG = "aspect_aby";

  @Pointcut("execution(@ * *(..))")
  public void firstMethodAnnotationBehavior() {
  }

  @Pointcut("execution(* ())")
  public void secondMethodAnnotationBehavior() {
  }

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

    MethodSignature methodSignature = (MethodSignature) ();
    // Class name    String className = ().getSimpleName();
    // Method name    String methodName = ();
    // Function name    IFirstAnnotation behaviorTrace = ()
        .getAnnotation();
    String value = ();
// String value = "click";    long start = ();
    Object result = ();
    long duration = () - start;
    (TAG, ("The %s method in the %s class executes the %s function, time-consuming: %dms", className, methodName, value, duration));
    ((), (, "The %s method in the %s class executes the %s function, time-consuming: %dms", className, methodName, value, duration), Toast.LENGTH_SHORT).show();
    return result;
  }
}

@Aspect specifies the aspect class; @Pointcut point cutting; @Around is a type of Advice in the cutting method, which means inserting code before and after the cutting point, as well as @Before and @After; Pointcut syntax, execution, which means inserting code before and after the execution of the internal code of the method according to Advice, which means inserting code before and after the calling method according to Advice...

Page call

@IFirstAnnotation("Test Aspect")
public void aspectClick(View view) {
   try {
     (new Random().nextInt(1000));
   } catch (InterruptedException e) {
     ();
   }
 }

@IFirstAnnotation call annotation, () is the value of the value written in IFirstAnnotation. After removing value(), remove() here ()

Note: If Context is used in the MethodBehaviorAspect class, you can directly convert it to Context using the() type. This is because the project uses databinding, and some of the values ​​obtained by getTarget() cannot be forced to convert to Context, so the Context obtained by MyApplication here is used.

This is just a personal initial attempt. Of course, there are still many contents to learn. I just read a few articles about AOP written by someone on CSDN. They are all very detailed. I give one of the addresses and read them yourself:https:///article/

The above is all the content of this article. I hope it will be helpful to everyone's study and I hope everyone will support me more.