1. Basic introduction
1. AOP
Before we get to AspectJ, let’s look at another term: AOP
1.1 concept
AOP for the abbreviation of Aspect Oriented Programming, meaning: section-oriented Programming, it can be implemented through pre-compilation and runtime dynamic proxy without modifying the source code to dynamically add a unified function of a technology.
1.2 role
What can AOP do? For example, android is prone to View being clicked continuously. Normally, we can record the time of the last click in the onClick event of a View and compare it, and the multiple clicks within 1s will be ignored. But regardless of the entire application, there are so many clickable views on a screen, should we add the same processing logic to each view’s onClick? AOP can help us unify the processing.
1.3 Implementation Mode
AOP implementations fall into static and dynamic categories
- Static: At compile time, the aspects are compiled directly into the target bytecode file, generating static AOP proxy classes (AspectJ, etc.)
- Dynamic mode: Dynamically generate proxy classes for the interface at runtime (mainly: Spring AOP, dynamic proxy, custom class loader, etc.)
2. AspectJ
With AOP understood, let’s turn to AspectJ’s official ProgGuide
2.1 concept
AspectJ is a section-oriented framework that extends the Java language. AspectJ defines the AOP syntax, which has a specialized compiler for generating Class files that comply with the Java byte-encoding specification. Simply put, AspectJ is an implementation framework for AOP.
2.2 the use of
AspectJ uses a special compiler (AJC) to weave in code at compile time without changing the code. Therefore, it is necessary for us to have a look at the official AJC documentation. Ajc is colloquially known as the AspectJ compiler, and as you can see in the documentation above, you can configure a number of parameters.
Two, basic use
1. Use it as a Gradle Plugin
# Developing Custom Gradle Plugins
- Build script
- buildSrc project
- Standalone project
I’ll cover the details in a separate post, but I’ll just use the Standalone Project to introduce the use of AspectJ
1.1 Creating the Android Module: libplugin
Create an Android Library and remove unnecessary Java folders, androidmanifest.xml, etc. Since the plug-in is written in Groovy, delete Java and recreate the Groovy folder.
1.2 modify the build. Gradle
Dependencies {implementation gradleApi(); // Gradle SDK implementation LocalGroovy () / / groovy SDK implementation 'org. Aspectj: aspectjtools:, version 1.8.1'} / / used to release the plug-in, other projects can be referenced by configuration apply plugin: 'maven-publish' repositories { google() jcenter() mavenCentral() } afterEvaluate { publishing { publications { release(MavenPublication) { from components.java groupId = 'com.king.plugin' artifactId = 'AspectJPlugin' version = '1.0.0'}} repositories {maven {allowInsecureProtocol true = uri('.. /repo') } } } }Copy the code
1.3 Writing plug-ins
Inherit org.gradle.api.Plugin and write logic in Apply
public class AspectJPlugin implements Plugin<Project> { @Override void apply(Project project) { project.dependencies { Implementation 'org. Aspectj: aspectjrt: 1.8.9'} project. The android. ApplicationVariants. All {variant - > def javaCompile = Variation. 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)] 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; } } } } } }Copy the code
1.4 Create the Properties file and associate the plug-in
The specific file structure is shown in the following figure
1.5 Building and Publishing
Open gradle and you can see a publish task under the libplugin. Double-click to run it
The REPo folder is generated under the AspectJDemo directory and the corresponding plug-in is generated
1.5 This plug-in is used in app Module
The plug-in generated above the build.gradle configuration of the project
Maven {url('repo')} mavenCentral()} dependencies {classpath "Com. Android. Tools. Build: gradle: 7.0.3" / / configure the plug-in classpath "com. King. The plugin: AspectJPlugin: 1.0.0" classpath "Org. Aspectj: aspectjrt: 1.8.9" allprojects}} {repositories {Google () maven {url (' ' ')} mavenCentral ()}}Copy the code
Use this plugin in your App Module’s build.gradle
Com. Android. Plugins {id 'application'} / / using plug-in import com. King. The plugin. AspectJPlugin apply plugin: AspectJPlugin } dependencies { ... Implementation 'org. Aspectj: aspectjrt: 1.8.9'}Copy the code
1.6 summarize
Now you can use AspectJ normally in your project. Here is a brief introduction to the use of AspectJ, so I will not go into details above
2. Use the AspectJ Plugin written by someone else
The above steps are tedious, so someone wrote a plugin for them: gradle_plugin_android_aspectjx
The main use process is as follows:
2.1 Project build.gradle configuration
buildscript { ... dependencies { ... The classpath 'com. Hujiang. Aspectjx: gradle - android plugin - aspectjx: mid-atlantic moved'}}Copy the code
2.2 Build. gradle configuration for app Module
apply plugin: Aspectjx {include 'com.king' // exclude: } // AspectJx switch, default is true aspectjx {enabled true}Copy the code
2.3 summarize
At this point, you can use AspectJ in your projects normally, which is much more convenient than the above method. I’ll add the corresponding demo later