在Android中使用一般有两种方式,一种是通过gradle配置,一种是自定义plugin。先来看第一种。这种方式比较简单,只需要修改两个文件即可。 一,project/build.gradle中添加如下内容
buildscript {
repositories {
google()
jcenter()
mavenCentral()
maven { url "https://oss.sonatype.org/content/repositories/snapshots/" }
maven {
url "https://maven.google.com"
}
}
dependencies {
classpath 'com.android.tools.build:gradle:3.2.1'
classpath 'org.aspectj:aspectjtools:1.9.0'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
allprojects {
repositories {
google()
jcenter()
mavenCentral()
}
}
task clean(type: Delete) {
delete rootProject.buildDir
}
二,在app/build.gradle中添加如下代码
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.8",
"-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 plugin的方式
- 同样是新建项目AspectDemo2,然后新建Androidlibrary,取名plugin。在project模式下删除这个library下的src/main下的所有文件
- 删除plugin/build.gradle中所有并添加如下
apply plugin: 'groovy'
apply plugin: 'maven'
dependencies {
implementation gradleApi()
implementation localGroovy()
implementation"org.aspectj:aspectjtools:1.9.0"
implementation"org.aspectj:aspectjrt:1.9.0"
}
repositories {
mavenCentral()
}
uploadArchives {
repositories.mavenDeployer {
//本地仓库路径,这里是放到项目根目录下的repo文件夹
repository(url:uri('../repo'))
//下面这三行则是定义生成依赖包的名称为com.mwy:aspectj.demo:1.0.0
//这个主要是在项目根目录的build.gradle文件中引用的样式(classpath'com.mwy:aspectj.demo:1.0.0')
//groupId为组织或公司名称,artifactId为项目名或者模块儿名,version为项目或模块的当前版本号
pom.groupId = 'com.mwy'
pom.artifactId = "aspectj.demo"
pom.version = '1.0.0'
}
}
- 在src/main目录下新建文件夹groovy,并在该文件夹中新建package,这里如com.mwy.plugin(接下来的groovy文件会在该包下)
- 在com.mwy.plugin中新建文件AspectJPlugin.groovy
public class AspectJPlugin implements Plugin<Project>{
@Override
void apply(Project project) {
final def log = project.logger
project.dependencies {
implementation 'org.aspectj:aspectjrt:1.9.0'
}
project.android.applicationVariants.all { variant ->
JavaCompile 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);
println()
println("####################################################################")
println("######## ########")
println("######## ########")
println("######## This is a aspectJ demo 编译插件 ########")
println("######## ########")
println("######## ########")
println("####################################################################")
println()
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;
}
}
}
}
}
}
- 在src/main目录下新建目录resources/META-INF/gradle-plugins,然后在这个路径下新建一个后缀名为.properties的文件(com.mwy.aspectj.properties),注意这里的文件名会在引用该插件,即在app/build.gradle中引用(apply plugin: 'com.mwy.aspectj'),该文件内容就是声明plugin的位置
implementation-class=com.yazon.plugin.AspectJPlugin
- 生成该jar包:studio右侧Gradle-upload-uploadArchives,成功之后可在项目的根目录下看到文件夹repo
- 使用plugin: 在project/build.gradle中添加本地maven以及刚刚编译好的包
buildscript {
repositories {
google()
jcenter()
maven {
url uri('repo')
}
}
dependencies {
classpath 'com.android.tools.build:gradle:3.2.1'
classpath'com.mwy:aspectj.demo:1.0.0'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
在app/build.gradle中添加引用:
apply plugin: 'com.mwy.aspectj'
还用之前测试代码进行验证:
@Aspect
public class TestAspectJ {
@Around("execution(* *(..))")
public void testAround(ProceedingJoinPoint joinPoint) throws Throwable {
long startNanoTime = System.nanoTime();
joinPoint.proceed();
long endNanoTime = System.nanoTime();
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
//方法名
String name = signature.getName();
Log.i("tag", "name = " + name);
Method method = signature.getMethod();
//这里拿到方法之后还可以进行其他操作,比如拿到注解
//method.getAnnotation(TestAnnotation.class);
//返回值类型
Class returnType = signature.getReturnType();
Log.i("tag", "returnType = " + returnType.getName());
//方法所在类名
Class declaringType = signature.getDeclaringType();
Log.i("tag", "declaringType = " + declaringType.getCanonicalName());
//参数类型
Class[] parameterTypes = signature.getParameterTypes();
for (Class cls : parameterTypes) {
Log.i("tag", " cls = " + cls.getSimpleName());
}
//参数名
String[] parameterNames = signature.getParameterNames();
for (String param : parameterNames) {
Log.i("tag", " param = " + param);
}
Log.i("tag", String.valueOf(endNanoTime - startNanoTime));
}
}
上面定义的切点是在所有方法中插入代码,而MainActivity中的代码为
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Log.i("tag", "onCreate execute complete");
}
}
实际运行后的打点log显示为
