下载aspectj 地址 :http://www.eclipse.org/aspectj/downloads.php
下载aspectj的adt地址:http://www.eclipse.org/ajdt/downloads/#43zips
build.gradle aspectJ 写法:http://fernandocejas.com/2014/08/03/aspect-oriented-programming-in-android/
有关注解相关基础知识可以参考:
Java 注解完全解析.
有关AOP相关基础知识可以参考:
浅谈Android面向切面编程(AOP)
深入理解Android之AOP
Android进阶系列之AOP面向切面编程
demo实例代码
app目录下build.gradle文件配置:
import org.aspectj.bridge.IMessage
import org.aspectj.bridge.MessageHandler
import org.aspectj.tools.ajc.Main
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath 'org.aspectj:aspectjtools:1.8.9'
classpath 'org.aspectj:aspectjweaver:1.8.9'
}
}
plugins {
id 'com.android.application'
}
repositories {
mavenCentral()
}
android {
compileSdkVersion 30
buildToolsVersion "30.0.2"
defaultConfig {
applicationId "com.test.aopdemo"
minSdkVersion 16
targetSdkVersion 30
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
}
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;
}
}
}
}
dependencies {
implementation 'androidx.appcompat:appcompat:1.1.0'
implementation 'com.google.android.material:material:1.1.0'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
testImplementation 'junit:junit:4.+'
androidTestImplementation 'androidx.test.ext:junit:1.1.1'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
implementation files('libs/aspectjrt.jar')
}
布局文件activity_main.xml:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
>
<Button
android:layout_width="match_parent"
android:layout_height="50dp"
android:text="摇一摇"
android:onClick="mShake"
android:gravity="center"
android:layout_marginTop="20dp"
/>
<Button
android:layout_width="match_parent"
android:layout_height="50dp"
android:text="发语音"
android:onClick="mAudio"
android:gravity="center"
android:layout_marginTop="20dp"
/>
<Button
android:layout_width="match_parent"
android:layout_height="50dp"
android:text="发文字"
android:onClick="mText"
android:gravity="center"
android:layout_marginTop="20dp"
/>
</LinearLayout>
MainActivity.java
package com.test.aopdemo;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.os.SystemClock;
import android.util.Log;
import android.view.View;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.logging.SimpleFormatter;
public class MainActivity extends AppCompatActivity {
public final static String TAG = "abc";
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
@BehaviorTrace(value = "摇一摇")
public void mShake(View view) {
SystemClock.sleep(3000);
}
@BehaviorTrace(value = "语音")
public void mAudio(View view) {
SystemClock.sleep(3000);
}
@BehaviorTrace(value = "文字")
public void mText(View view) {
SystemClock.sleep(3000);
}
}
BehaviorTrace.java
package com.test.aopdemo;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface BehaviorTrace {
String value();
}
BehaviorAspect.java
package com.test.aopdemo;
import android.util.Log;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* 切面
*/
@Aspect
public class BehaviorAspect {
private static final String TAG = "abc";
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
/**
* 切点
*/
@Pointcut("execution(@com.test.aopdemo.BehaviorTrace * *(..))")
public void annoBehavior(){
}
/**
* 切面
*/
@Around("annoBehavior()")
public Object dealPoint(ProceedingJoinPoint point) throws Throwable {
// 方法执行前
MethodSignature methodSignature = (MethodSignature) point.getSignature();
BehaviorTrace behaviorTrace = methodSignature.getMethod().getAnnotation(BehaviorTrace.class);
String contentType = behaviorTrace.value();
Log.d(TAG, contentType + "使用时间:" + simpleDateFormat.format(new Date()));
long begin = System.currentTimeMillis();
Object object = point.proceed();
// 方法执行完成
Log.d(TAG, contentType + "结束时间:" + simpleDateFormat.format(new Date()));
Log.d(TAG, "消耗时间:" + (System.currentTimeMillis() - begin) + "ms");
return object;
}
}