Skip to content

Commit

Permalink
Merge pull request #61 from wurensen/hotfix/3.3.2
Browse files Browse the repository at this point in the history
Hotfix/3.3.2
  • Loading branch information
wurensen authored Dec 20, 2022
2 parents c4bd65c + 09e8cce commit d9334ea
Show file tree
Hide file tree
Showing 12 changed files with 314 additions and 24 deletions.
8 changes: 7 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,12 @@

版本日志格式基于 [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),版本号遵循 [语义化版本 2.0.0](https://semver.org/spec/v2.0.0.html)

## [3.3.2] - 2022-12-20

### Fixed

- 修复:androidTest构建错误问题([#56](https://github.com/wurensen/gradle_plugin_android_aspectjx/issues/56)

## [3.3.1] - 2022-10-25

### Fixed
Expand Down Expand Up @@ -80,7 +86,7 @@

### Fixed

- 修复:Kotlin项目禁用插件或不需要进行任何织入时,会发送类丢失的问题[#26](https://github.com/wurensen/gradle_plugin_android_aspectjx/issues/26)
- 修复:Kotlin项目禁用插件或不需要进行任何织入时,会发生类丢失的问题[#26](https://github.com/wurensen/gradle_plugin_android_aspectjx/issues/26)

## 2.0.14 (2021-12-07)

Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ AspectJX

> [原作者说明文档](./README-old.md)
## 最新版本(3.3.1
## 最新版本(3.3.2

接入或者升级前,请先[查看完整版本日志](CHANGELOG.md)

Expand Down
2 changes: 1 addition & 1 deletion app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ android {
versionCode 1
versionName "1.0"

testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}

buildTypes {
Expand Down
14 changes: 14 additions & 0 deletions app/src/main/java/com/lancewu/aspectj/AnnotationsKt.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.lancewu.aspectj

/**
* Created by LanceWu on 2022/12/19
*
* 注解测试
*/
@Retention(AnnotationRetention.RUNTIME)
@Target(AnnotationTarget.FUNCTION, AnnotationTarget.CONSTRUCTOR)
annotation class AOPLog(val value: String = "AOPLog")

@Retention(AnnotationRetention.RUNTIME)
@Target(AnnotationTarget.FUNCTION)
annotation class Permissions(val value: Array<String>)
144 changes: 144 additions & 0 deletions app/src/main/java/com/lancewu/aspectj/LogAspect.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
package com.lancewu.aspectj;

import android.os.Looper;
import android.os.Trace;
import android.util.Log;

import androidx.annotation.NonNull;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.CodeSignature;
import org.aspectj.lang.reflect.MethodSignature;

import java.util.concurrent.TimeUnit;

/**
* Created by LanceWu on 2022/12/19.<br>
* TODO 类说明
*/
@Aspect
public class LogAspect {

/**
* 构造方法切入点
*/
@Pointcut("execution(@com.lancewu.aspectj.AOPLog *.new(..))")
public void constructor() {
}

/**
* 方法切入点
*/
@Pointcut("execution(@com.lancewu.aspectj.AOPLog * *(..))")
public void method() {
}

/**
* 在连接点进行方法替换
*/
@Around("(method() || constructor()) && @annotation(log)")
public Object aroundJoinPoint(ProceedingJoinPoint joinPoint, AOPLog log) throws Throwable {
enterMethod(joinPoint, log);

long startNanos = System.nanoTime();
Object result = joinPoint.proceed();
long stopNanos = System.nanoTime();

exitMethod(joinPoint, log, result, TimeUnit.NANOSECONDS.toMillis(stopNanos - startNanos));

return result;
}

/**
* 方法执行前切入
*/
private void enterMethod(ProceedingJoinPoint joinPoint, AOPLog log) {
CodeSignature codeSignature = (CodeSignature) joinPoint.getSignature();

// 方法所在类
String className = codeSignature.getDeclaringType().getName();
// 方法名
String methodName = codeSignature.getName();
// 方法参数名集合
String[] parameterNames = codeSignature.getParameterNames();
// 方法参数值集合
Object[] parameterValues = joinPoint.getArgs();

//记录并打印方法的信息
StringBuilder builder = getMethodLogInfo(className, methodName, parameterNames, parameterValues);

log(log.value(), builder.toString());

final String section = builder.substring(2);
Trace.beginSection(section);
}

/**
* 获取方法的日志信息
*
* @param className 类名
* @param methodName 方法名
* @param parameterNames 方法参数名集合
* @param parameterValues 方法参数值集合
*/
@NonNull
private StringBuilder getMethodLogInfo(String className, String methodName, String[] parameterNames, Object[] parameterValues) {
StringBuilder builder = new StringBuilder("\u21E2 ");
builder.append(className)
.append(".")
.append(methodName)
.append('(');
for (int i = 0; i < parameterValues.length; i++) {
if (i > 0) {
builder.append(", ");
}
builder.append(parameterNames[i]).append('=');
builder.append(parameterValues[i]);
}
builder.append(')');

if (Looper.myLooper() != Looper.getMainLooper()) {
builder.append(" [Thread:\"").append(Thread.currentThread().getName()).append("\"]");
}
return builder;
}

/**
* 方法执行完毕,切出
*
* @param result 方法执行后的结果
* @param lengthMillis 执行方法所需要的时间
*/
private void exitMethod(ProceedingJoinPoint joinPoint, AOPLog log, Object result, long lengthMillis) {
Trace.endSection();

Signature signature = joinPoint.getSignature();

String className = signature.getDeclaringType().getName();
String methodName = signature.getName();

StringBuilder builder = new StringBuilder("\u21E0 ")
.append(className)
.append(".")
.append(methodName)
.append(" [")
.append(lengthMillis)
.append("ms]");

// 判断方法是否有返回值
if (signature instanceof MethodSignature && ((MethodSignature) signature).getReturnType() != void.class) {
builder.append(" = ");
builder.append(result.toString());
}

log(log.value(), builder.toString());
}

private void log(String tag, String msg) {
Log.d(tag, msg);
}
}
23 changes: 23 additions & 0 deletions app/src/main/java/com/lancewu/aspectj/MainActivity.kt
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package com.lancewu.aspectj

import android.Manifest
import android.graphics.Bitmap
import android.os.Bundle
import android.util.Log
import android.view.View
import android.view.View.OnClickListener
import android.widget.Button
Expand All @@ -22,6 +24,9 @@ class MainActivity : AppCompatActivity() {
LibraryJavaTest().test()
LibraryCompileOnlyTest().test(Bitmap.createBitmap(10, 10, Bitmap.Config.ARGB_8888))
clickAspect()
findViewById<Button>(R.id.two_annotation_btn).setOnClickListener {
testAnnotationsWrapper(this)
}
}

private fun clickAspect() {
Expand All @@ -39,4 +44,22 @@ class MainActivity : AppCompatActivity() {
private fun toast() {
// 通过aop织入
}

@Permissions([Manifest.permission.CAMERA])
private fun testAnnotationsWrapper(activity: MainActivity) {
Log.d("testAnnotationsWrapper", "call")
testAnnotations()
}

/**
* 多个注解织入,在织入处理时如果存在延期调用,会出现EmptyStackException异常,因为这不符合aspectj机制设计。
* 解决办法是,存在延期调用业务时,独立一个函数,比如这边的testAnnotationsWrapper,注解拆分出来处理
*
* [详情:多注解异常](https://github.com/wurensen/gradle_plugin_android_aspectjx/issues/60)
*/
@AOPLog
// @Permissions([Manifest.permission.CAMERA])
private fun testAnnotations() {
Log.d("testAnnotations", "call")
}
}
79 changes: 79 additions & 0 deletions app/src/main/java/com/lancewu/aspectj/PermissionsAspect.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
package com.lancewu.aspectj;

import android.app.Activity;
import android.content.DialogInterface;
import android.util.Log;

import androidx.appcompat.app.AlertDialog;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;

import java.util.Arrays;

/**
* Created by LanceWu on 2022/12/19.<br>
* TODO 类说明
*/
@Aspect
public class PermissionsAspect {

/**
* 方法切入点
*/
@Pointcut("execution(@com.lancewu.aspectj.Permissions * *(..))")
public void method() {
}

/**
* 在连接点进行方法替换
*/
@Around("method() && @annotation(permissions)")
public void aroundJoinPoint(ProceedingJoinPoint joinPoint, Permissions permissions) {
Activity activity = null;

// 方法参数值集合
Object[] parameterValues = joinPoint.getArgs();
for (Object arg : parameterValues) {
if (!(arg instanceof Activity)) {
continue;
}
activity = (Activity) arg;
break;
}

if (activity == null || activity.isFinishing() || activity.isDestroyed()) {
Log.e("PermissionsAspect", "The activity has been destroyed and permission requests cannot be made");
return;
}

requestPermissions(joinPoint, activity, permissions.value());
}

private void requestPermissions(ProceedingJoinPoint joinPoint, Activity activity, String[] permissions) {
Log.d("PermissionsAspect", "申请权限:" + Arrays.toString(permissions));
// FIXME: 2022/12/20 嵌套around-advice时,采用延期调用或是中断-恢复的方式,来调用joinPoint.proceed(),
// 会出现EmptyStackException异常,原因是aspectj设计上,对于嵌套的around-advice,采取栈的方式存储;
// 相关问题可参照:https://github.com/eclipse/org.aspectj/issues/128
// 该issues是多线程调用,在1.9.9版本已修复,但类似以下的使用方式不符合设计
new AlertDialog.Builder(activity)
.setCancelable(false)
.setMessage("模拟申请权限弹窗")
.setPositiveButton("点击模拟获取权限结果", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
Log.d("PermissionsAspect", "模拟申请权限结束");
// 获得权限,执行原方法
try {
joinPoint.proceed();
} catch (Throwable e) {
e.printStackTrace();
}
}
})
.show();
}

}
10 changes: 9 additions & 1 deletion app/src/main/res/layout/activity_main.xml
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,17 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />

<Button
android:id="@+id/two_annotation_btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="two_annotation_btn"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@id/btn" />

</androidx.constraintlayout.widget.ConstraintLayout>
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,14 @@ import org.gradle.api.Project
import java.io.File

/**
* Aspect处理<br>
* Aspect处理类
*
* 自定义transform几个问题需要注意:
* <ul>
* <li>对于多flavor的构建,每个flavor都会执行transform</li>
* <li>对于开启gradle daemon的情况(默认开启的,一般也不会去关闭),每次构建都是运行在同一个进程上,
* 所以要注意到有没有使用到有状态的静态或者单例,如果有的话,需要在构建结束进行处理,否则会影响到后续的构建</li>
* <li>增量构建时,要注意是否需要删除之前在outputProvider下已产生的产物</li>
* </ul>
* - 对于多flavor的构建,每个flavor都会执行transform
* - 对于开启gradle daemon的情况(默认开启的,一般也不会去关闭),每次构建都是运行在同一个进程上,
* 所以要注意到有没有使用到有状态的静态或者单例,如果有的话,需要在构建结束进行处理,否则会影响到后续的构建
* - 增量构建时,要注意是否需要删除之前在outputProvider下已产生的产物
*
* @author simon* @version 1.0.0* @since 2018-03-12
*/
class AJXTransform(project: Project) : Transform() {
Expand All @@ -50,12 +50,12 @@ class AJXTransform(project: Project) : Transform() {
init {
project.afterEvaluate {
// 获取配置
ajxExtension = project.extensions.findByType(AJXExtension::class.java) ?: AJXExtension()
ajxExtension = it.extensions.findByType(AJXExtension::class.java) ?: AJXExtension()
// 规则重整
optimizeExtension(ajxExtension)
LoggerHolder.logger.quiet("[$TAG] AJXExtension after optimize:$ajxExtension")
// 获取android配置以及对应编译选项
createVariantCompileOptions(AndroidConfig(project))
createVariantCompileOptions(AndroidConfig(it))
// 设置运行变量
System.setProperty("aspectj.multithreaded", "true")
}
Expand Down Expand Up @@ -98,6 +98,7 @@ class AJXTransform(project: Project) : Transform() {
}
variantCompileOptions[variant.name] = compileOptions
}
LoggerHolder.logger.quiet("[$TAG] variantCompileOptions:${variantCompileOptions.keys}")
}

override fun getName(): String {
Expand Down
Loading

0 comments on commit d9334ea

Please sign in to comment.