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.