在了解AspectJ前,我们首先了解另外一个名词:AOP
AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,它可以通过预编译方式和运行期动态代理实现在不修改源代码的情况下给程序动态统一添加功能的一种技术。
AOP可以做什么呢?举个例子,android中容易发生View被连续点击的情况,正常我们可以在某个view的onClick事件中记录上一次点击的时间点然后进行对比,在1s内的多次点击就被忽略掉。但是,先不说整个应用,某个界面上可点击的view就有那么多,我们要为每一个view的onClick都增加同样的处理逻辑么?AOP就可以帮我们进行统一处理。
AOP实现主要分为 静态 和 动态 两种
理解完AOP,我们再来看AspectJ官方progguide
AspectJ是一个面向切面的框架,它扩展了Java语言。AspectJ定义了AOP语法,它有一个专门的编译器用来生成遵守Java字节编码规范的Class文件。简单来说,AspectJ是AOP的一种实现框架。
AspectJ是在编译期通过特殊的编译器(ajc)在不改变代码的前提下织入代码。所以我们有必要了解下ajc官方文档。ajc通俗讲就是AspectJ编译器,在上方文档可以看到,可以进行一系列的参数配置。
gradle的plugin创建方式也有多种,# Developing Custom Gradle Plugins:
后续我会单独一篇文章详细介绍,这里只使用Standalone project的方式介绍AspectJ的使用
创建一个Android Library,然后删除掉不必要的java文件夹、Androidmanifest.xml等文件。由于插件使用groovy编写,所以删掉java,重新创建groovy文件夹。
plugins {
// 使用的是groovy
id 'groovy'
}
dependencies {
implementation gradleApi()//gradle sdk
implementation localGroovy()//groovy sdk
implementation 'org.aspectj:aspectjtools:1.8.1'
}
// 用于发布该插件,其他工程可通过配置引用
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
// 指定发布的位置为当前工程的repo目录下
url = uri('../repo')
}
}
}
}
复制代码
继承org.gradle.api.Plugin,在apply编写逻辑
public class AspectJPlugin implements Plugin<Project> {
@Override
void apply(Project project) {
project.dependencies {
implementation 'org.aspectj:aspectjrt:1.8.9'
}
project.android.applicationVariants.all { variant ->
def 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)]
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功能区展开,可以看到libplugin下边有个publish的task,双击运行
就会在AspectJDemo目录下生成repo文件夹,并生成了相应的插件
在项目的build.gradle配置上方生成的插件
buildscript {
repositories {
google()
// 配置插件路径
maven {
url('repo')
}
mavenCentral()
}
dependencies {
classpath "com.android.tools.build:gradle:7.0.3"
// 配置插件
classpath "com.king.plugin:AspectJPlugin:1.0.0"
classpath "org.aspectj:aspectjrt:1.8.9"
}
}
allprojects {
repositories {
google()
maven {
url('repo')
}
mavenCentral()
}
}
复制代码
在app module 的build.gradle使用该插件
plugins {
id 'com.android.application'
}
// 使用插件
import com.king.plugin.AspectJPlugin
apply plugin: AspectJPlugin
}
dependencies {
...
implementation 'org.aspectj:aspectjrt:1.8.9'
}
复制代码
至此,你已经可以正常的在项目中使用aspectj了~这里主要介绍aspectj的使用,所以不详细介绍上边的禁止view频繁点击demo,具体代码在gitee: Demo下载地址
上述的步骤挺繁琐,所以有人专门写好了相应的插件:gradle_plugin_android_aspectjx
主要的使用流程如下:
buildscript {
...
dependencies {
...
classpath 'com.hujiang.aspectjx:gradle-android-plugin-aspectjx:2.0.8'
}
}
复制代码
apply plugin: 'android-aspectjx'
// 配置需要编译包含的文件
aspectjx {
include 'com.king'
// exclude:排除
}
// aspectjx的开关,默认为true
aspectjx {
enabled true
}
复制代码
至此,已经可以正常在项目中使用aspectj了~相比起来,会比上边的方法方便很多。稍后再添加上这个相应的demo
本文系转载,前往查看
如有侵权,请联系 cloudcommunity@tencent.com 删除。
本文系转载,前往查看
如有侵权,请联系 cloudcommunity@tencent.com 删除。