From f2cb9a43148410b3577a1040cbb55e3e5ee4d21f Mon Sep 17 00:00:00 2001 From: tianxiangyu <96164429+FlyJingFish@users.noreply.github.com> Date: Wed, 3 Apr 2024 19:23:38 +0800 Subject: [PATCH 1/3] =?UTF-8?q?1=E3=80=81=E5=AE=8C=E5=96=84=E7=BB=87?= =?UTF-8?q?=E5=85=A5=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../AndroidAopJoinPoint.java | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/android-aop-annotation/src/main/java/com/flyjingfish/android_aop_annotation/AndroidAopJoinPoint.java b/android-aop-annotation/src/main/java/com/flyjingfish/android_aop_annotation/AndroidAopJoinPoint.java index 5b6b0152..45e2abda 100644 --- a/android-aop-annotation/src/main/java/com/flyjingfish/android_aop_annotation/AndroidAopJoinPoint.java +++ b/android-aop-annotation/src/main/java/com/flyjingfish/android_aop_annotation/AndroidAopJoinPoint.java @@ -22,6 +22,7 @@ public final class AndroidAopJoinPoint { private Method targetMethod; private Method originalMethod; private String cutMatchClassName; + private String paramsKey; public AndroidAopJoinPoint(String targetClassName, Object target, String originalMethodName, String targetMethodName) { // this.targetClassName = targetClassName; @@ -42,6 +43,18 @@ public void setCutMatchClassName(String cutMatchClassName) { public void setArgClassNames(String[] argClassNames) { this.mArgClassNames = argClassNames; + StringBuilder stringBuilder = new StringBuilder(); + stringBuilder.append("("); + int index = 0; + for (String argClassName : argClassNames) { + stringBuilder.append(argClassName); + if (index != argClassNames.length - 1){ + stringBuilder.append(","); + } + index++; + } + stringBuilder.append(")"); + paramsKey = stringBuilder.toString(); } public Object joinPointExecute() { @@ -133,10 +146,14 @@ public String toString() { public void setArgs(Object[] args) { this.mArgs = args; + getTargetMethod(); + } + + private void getTargetMethod(){ try { Class[] classes; if (mArgClassNames != null && mArgClassNames.length > 0) { - classes = new Class[args.length]; + classes = new Class[mArgClassNames.length]; int index = 0; for (String className : mArgClassNames) { try { From b18cc5a0200762794e20279c7e6b7a7e7ef1b92c Mon Sep 17 00:00:00 2001 From: FlyJingFish Date: Wed, 3 Apr 2024 22:50:27 +0800 Subject: [PATCH 2/3] =?UTF-8?q?1=E3=80=81=E5=87=8F=E5=B0=91=E5=8F=8D?= =?UTF-8?q?=E5=B0=84=E6=AC=A1=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../AndroidAopJoinPoint.java | 101 +++++++++--------- .../utils/AndroidAopBeanUtils.kt | 53 ++++++--- .../android_aop_annotation/utils/MethodMap.kt | 5 + 3 files changed, 95 insertions(+), 64 deletions(-) create mode 100644 android-aop-annotation/src/main/java/com/flyjingfish/android_aop_annotation/utils/MethodMap.kt diff --git a/android-aop-annotation/src/main/java/com/flyjingfish/android_aop_annotation/AndroidAopJoinPoint.java b/android-aop-annotation/src/main/java/com/flyjingfish/android_aop_annotation/AndroidAopJoinPoint.java index 45e2abda..f7a92f95 100644 --- a/android-aop-annotation/src/main/java/com/flyjingfish/android_aop_annotation/AndroidAopJoinPoint.java +++ b/android-aop-annotation/src/main/java/com/flyjingfish/android_aop_annotation/AndroidAopJoinPoint.java @@ -4,6 +4,7 @@ import com.flyjingfish.android_aop_annotation.base.BasePointCut; import com.flyjingfish.android_aop_annotation.base.MatchClassMethod; import com.flyjingfish.android_aop_annotation.utils.AndroidAopBeanUtils; +import com.flyjingfish.android_aop_annotation.utils.MethodMap; import java.lang.annotation.Annotation; import java.lang.reflect.Method; @@ -23,17 +24,26 @@ public final class AndroidAopJoinPoint { private Method originalMethod; private String cutMatchClassName; private String paramsKey; + private String methodKey; + private String targetClassName; public AndroidAopJoinPoint(String targetClassName, Object target, String originalMethodName, String targetMethodName) { -// this.targetClassName = targetClassName; - try { - targetClass = Class.forName(targetClassName); - } catch (ClassNotFoundException e) { - throw new RuntimeException(targetClassName + "的类名不可被混淆"); - } + this.targetClassName = targetClassName; this.target = target; this.originalMethodName = originalMethodName; this.targetMethodName = targetMethodName; + String key = targetClassName + "-" + target; + Class clazz = AndroidAopBeanUtils.INSTANCE.getClassCache(key); + if (clazz == null){ + try { + clazz = Class.forName(targetClassName); + AndroidAopBeanUtils.INSTANCE.putClassCache(key,clazz,target); + } catch (ClassNotFoundException e) { + throw new RuntimeException(targetClassName + "的类名不可被混淆"); + } + } + targetClass = clazz; + } @@ -43,18 +53,6 @@ public void setCutMatchClassName(String cutMatchClassName) { public void setArgClassNames(String[] argClassNames) { this.mArgClassNames = argClassNames; - StringBuilder stringBuilder = new StringBuilder(); - stringBuilder.append("("); - int index = 0; - for (String argClassName : argClassNames) { - stringBuilder.append(argClassName); - if (index != argClassNames.length - 1){ - stringBuilder.append(","); - } - index++; - } - stringBuilder.append(")"); - paramsKey = stringBuilder.toString(); } public Object joinPointExecute() { @@ -71,7 +69,7 @@ public Object joinPointExecute() { String annotationName = annotation.annotationType().getName(); String cutClassName = AndroidAopBeanUtils.INSTANCE.getCutClassName(annotationName); if (cutClassName != null) { - BasePointCut basePointCut = AndroidAopBeanUtils.INSTANCE.getBasePointCut(proceedJoinPoint, cutClassName, annotationName); + BasePointCut basePointCut = AndroidAopBeanUtils.INSTANCE.getBasePointCut(proceedJoinPoint, cutClassName, annotationName,targetClassName,methodKey); if (basePointCut != null) { PointCutAnnotation pointCutAnnotation = new PointCutAnnotation(annotation, basePointCut); basePointCuts.add(pointCutAnnotation); @@ -80,7 +78,7 @@ public Object joinPointExecute() { } if (cutMatchClassName != null) { - MatchClassMethod matchClassMethod = AndroidAopBeanUtils.INSTANCE.getMatchClassMethod(proceedJoinPoint, cutMatchClassName); + MatchClassMethod matchClassMethod = AndroidAopBeanUtils.INSTANCE.getMatchClassMethod(proceedJoinPoint, cutMatchClassName,targetClassName,methodKey); PointCutAnnotation pointCutAnnotation = new PointCutAnnotation(matchClassMethod); basePointCuts.add(pointCutAnnotation); } @@ -150,6 +148,29 @@ public void setArgs(Object[] args) { } private void getTargetMethod(){ + StringBuilder stringBuilder = new StringBuilder(); + stringBuilder.append("("); + if (mArgClassNames != null && mArgClassNames.length > 0){ + int index = 0; + for (String argClassName : mArgClassNames) { + stringBuilder.append(argClassName); + if (index != mArgClassNames.length - 1){ + stringBuilder.append(","); + } + index++; + } + } + stringBuilder.append(")"); + paramsKey = stringBuilder.toString(); + methodKey = originalMethodName + paramsKey; + + String key = targetClassName +"-" + target + "-" + methodKey; + MethodMap methodMap = AndroidAopBeanUtils.INSTANCE.getMethodMapCache(key); + if (methodMap != null){ + targetMethod = methodMap.getTargetMethod(); + originalMethod = methodMap.getOriginalMethod(); + return; + } try { Class[] classes; if (mArgClassNames != null && mArgClassNames.length > 0) { @@ -167,45 +188,25 @@ private void getTargetMethod(){ } else { classes = new Class[0]; } - Class tClass = null; - if (target != null) { - tClass = target.getClass(); - } - if (tClass == null) { - tClass = targetClass; - } + Class tClass = targetClass; if (tClass == null) { throw new RuntimeException("织入代码异常"); } - try { - targetMethod = tClass.getDeclaredMethod(targetMethodName, classes); - } catch (NoSuchMethodException e) { - try { - targetMethod = tClass.getMethod(targetMethodName, classes); - } catch (NoSuchMethodException ex) { - targetMethod = targetClass.getDeclaredMethod(targetMethodName, classes); - } - } + targetMethod = tClass.getDeclaredMethod(targetMethodName, classes); try { originalMethod = tClass.getDeclaredMethod(originalMethodName, classes); - } catch (NoSuchMethodException e) { - try { - originalMethod = tClass.getMethod(originalMethodName, classes); - } catch (NoSuchMethodException ex) { - try { - originalMethod = targetClass.getDeclaredMethod(originalMethodName, classes); - } catch (NoSuchMethodException exc) { - String realMethodName = getRealMethodName(originalMethodName); - if (realMethodName == null){ - throw new RuntimeException(exc); - } - originalMethod = targetClass.getDeclaredMethod(realMethodName, classes); - } + } catch (NoSuchMethodException exc) { + String realMethodName = getRealMethodName(originalMethodName); + if (realMethodName == null){ + throw new RuntimeException(exc); } + originalMethod = tClass.getDeclaredMethod(realMethodName, classes); } targetMethod.setAccessible(true); originalMethod.setAccessible(true); - } catch (NoSuchMethodException e) { + methodMap = new MethodMap(originalMethod,targetMethod); + AndroidAopBeanUtils.INSTANCE.putMethodMapCache(key,methodMap,target); + } catch (Exception e) { throw new RuntimeException(e); } } diff --git a/android-aop-annotation/src/main/java/com/flyjingfish/android_aop_annotation/utils/AndroidAopBeanUtils.kt b/android-aop-annotation/src/main/java/com/flyjingfish/android_aop_annotation/utils/AndroidAopBeanUtils.kt index e45c4710..99d54407 100644 --- a/android-aop-annotation/src/main/java/com/flyjingfish/android_aop_annotation/utils/AndroidAopBeanUtils.kt +++ b/android-aop-annotation/src/main/java/com/flyjingfish/android_aop_annotation/utils/AndroidAopBeanUtils.kt @@ -12,6 +12,8 @@ internal object AndroidAopBeanUtils { private val mBasePointCutMap = ConcurrentHashMap?>() private val mMatchClassMethodMap = ConcurrentHashMap() private val mTargetReferenceMap = ConcurrentHashMap>() + private val mTargetMethodMap = ConcurrentHashMap() + private val mTargetClassMap = ConcurrentHashMap>() private val mTargetKeyReferenceQueue = ReferenceQueue() private val mSingleIO: ExecutorService = Executors.newSingleThreadExecutor() @@ -22,15 +24,13 @@ internal object AndroidAopBeanUtils { return JoinAnnoCutUtils.getCutClassName(className) } - fun getBasePointCut(joinPoint: ProceedJoinPoint, clsName: String,annotationName : String): BasePointCut? { - val className = joinPoint.targetClass.name - val methodName = joinPoint.targetMethod.name - val key = "$className-${joinPoint.target}-$methodName-$annotationName" + fun getBasePointCut(joinPoint: ProceedJoinPoint, cutClassName: String, annotationName : String,targetClassName:String, methodKey : String): BasePointCut? { + val key = "$targetClassName-${joinPoint.target}-$methodKey-$annotationName" var basePointCut: BasePointCut? = mBasePointCutMap[key] if (basePointCut == null) { - basePointCut = getNewPointCut(clsName) + basePointCut = getNewPointCut(cutClassName) mBasePointCutMap[key] = basePointCut - observeTarget(joinPoint, key) + observeTarget(joinPoint.target, key) }else{ removeWeaklyReachableObjectsOnIOThread() } @@ -54,15 +54,13 @@ internal object AndroidAopBeanUtils { } - fun getMatchClassMethod(joinPoint: ProceedJoinPoint, clsName: String): MatchClassMethod { - val className = joinPoint.targetClass.name - val methodName = joinPoint.targetMethod.name - val key = "$className-${joinPoint.target}-$methodName-$clsName" + fun getMatchClassMethod(joinPoint: ProceedJoinPoint, cutClassName: String, targetClassName:String,methodKey : String): MatchClassMethod { + val key = "$targetClassName-${joinPoint.target}-$methodKey-$cutClassName" var matchClassMethod: MatchClassMethod? = mMatchClassMethodMap[key] if (matchClassMethod == null) { - matchClassMethod = getNewMatchClassMethod(clsName) + matchClassMethod = getNewMatchClassMethod(cutClassName) mMatchClassMethodMap[key] = matchClassMethod - observeTarget(joinPoint, key) + observeTarget(joinPoint.target, key) }else{ removeWeaklyReachableObjectsOnIOThread() } @@ -83,9 +81,34 @@ internal object AndroidAopBeanUtils { return matchClassMethod } - private fun observeTarget(joinPoint: ProceedJoinPoint,key :String){ + fun getMethodMapCache(key: String): MethodMap? { + val methodMap = mTargetMethodMap[key] + if (methodMap != null){ + removeWeaklyReachableObjectsOnIOThread() + } + return methodMap + } + + fun putMethodMapCache(key: String, methodMap:MethodMap, target:Any?) { + mTargetMethodMap[key] = methodMap + observeTarget(target,key) + } + + fun getClassCache(key: String): Class<*>? { + val clazz = mTargetClassMap[key] + if (clazz != null){ + removeWeaklyReachableObjectsOnIOThread() + } + return clazz + } + + fun putClassCache(key: String, clazz:Class<*>, target:Any?) { + mTargetClassMap[key] = clazz + observeTarget(target,key) + } + + private fun observeTarget(target : Any?,key :String){ mSingleIO.execute{ - val target = joinPoint.target if (target != null){ val weakReference = KeyWeakReference(target,mTargetKeyReferenceQueue,key) mTargetReferenceMap[key] = weakReference @@ -108,6 +131,8 @@ internal object AndroidAopBeanUtils { mTargetReferenceMap.remove(ref.key) mBasePointCutMap.remove(ref.key) mMatchClassMethodMap.remove(ref.key) + mTargetMethodMap.remove(ref.key) + mTargetClassMap.remove(ref.key) } } while (ref != null) } diff --git a/android-aop-annotation/src/main/java/com/flyjingfish/android_aop_annotation/utils/MethodMap.kt b/android-aop-annotation/src/main/java/com/flyjingfish/android_aop_annotation/utils/MethodMap.kt new file mode 100644 index 00000000..bb005f99 --- /dev/null +++ b/android-aop-annotation/src/main/java/com/flyjingfish/android_aop_annotation/utils/MethodMap.kt @@ -0,0 +1,5 @@ +package com.flyjingfish.android_aop_annotation.utils + +import java.lang.reflect.Method + +class MethodMap(val originalMethod: Method,val targetMethod: Method) \ No newline at end of file From 1391ee80b2483c6587db250489a998479f053cdf Mon Sep 17 00:00:00 2001 From: FlyJingFish Date: Wed, 3 Apr 2024 23:05:08 +0800 Subject: [PATCH 3/3] =?UTF-8?q?1=E3=80=81=E5=8D=87=E7=BA=A7=E7=89=88?= =?UTF-8?q?=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 14 +++++++------- README_EN.md | 14 +++++++------- gradle.properties | 2 +- version.properties | 4 ++-- 4 files changed, 17 insertions(+), 17 deletions(-) diff --git a/README.md b/README.md index 9356898c..e1226e48 100644 --- a/README.md +++ b/README.md @@ -61,7 +61,7 @@ //必须项 👇 plugins { ... - id "io.github.FlyJingFish.AndroidAop.android-aop" version "1.5.1" + id "io.github.FlyJingFish.AndroidAop.android-aop" version "1.5.2" } ``` @@ -75,7 +75,7 @@ plugins { buildscript { dependencies { //必须项 👇 - classpath 'io.github.FlyJingFish.AndroidAop:android-aop-plugin:1.5.1' + classpath 'io.github.FlyJingFish.AndroidAop:android-aop-plugin:1.5.2' } } ``` @@ -86,7 +86,7 @@ buildscript { plugins { //必须项 👇 - id "io.github.FlyJingFish.AndroidAop.android-aop" version "1.5.1" apply false + id "io.github.FlyJingFish.AndroidAop.android-aop" version "1.5.2" apply false } ``` @@ -133,17 +133,17 @@ plugins { dependencies { //必须项 👇 - implementation 'io.github.FlyJingFish.AndroidAop:android-aop-core:1.5.1' - implementation 'io.github.FlyJingFish.AndroidAop:android-aop-annotation:1.5.1' + implementation 'io.github.FlyJingFish.AndroidAop:android-aop-core:1.5.2' + implementation 'io.github.FlyJingFish.AndroidAop:android-aop-annotation:1.5.2' //必须项 👇如果您项目内已经有了这项不用加也可以 implementation 'androidx.appcompat:appcompat:1.3.0' // 至少在1.3.0及以上 //非必须项 👇,如果你想自定义切面需要用到,⚠️支持Java和Kotlin代码写的切面 - ksp 'io.github.FlyJingFish.AndroidAop:android-aop-ksp:1.5.1' + ksp 'io.github.FlyJingFish.AndroidAop:android-aop-ksp:1.5.2' //非必须项 👇,如果你想自定义切面需要用到,⚠️只适用于Java代码写的切面 - annotationProcessor 'io.github.FlyJingFish.AndroidAop:android-aop-processor:1.5.1' + annotationProcessor 'io.github.FlyJingFish.AndroidAop:android-aop-processor:1.5.2' //⚠️上边的 android-aop-ksp 和 android-aop-processor 二选一 } ``` diff --git a/README_EN.md b/README_EN.md index 6ea9bbf9..78337119 100644 --- a/README_EN.md +++ b/README_EN.md @@ -60,7 +60,7 @@ Add directly to ```build.gradle``` of **app** //Required items 👇 plugins { ... - id "io.github.FlyJingFish.AndroidAop.android-aop" version "1.5.1" + id "io.github.FlyJingFish.AndroidAop.android-aop" version "1.5.2" } ``` @@ -74,7 +74,7 @@ old version buildscript { dependencies { //Required items 👇 - classpath 'io.github.FlyJingFish.AndroidAop:android-aop-plugin:1.5.1' + classpath 'io.github.FlyJingFish.AndroidAop:android-aop-plugin:1.5.2' } } ``` @@ -86,7 +86,7 @@ buildscript { plugins { //必须项 👇 - id "io.github.FlyJingFish.AndroidAop.android-aop" version "1.5.1" apply false + id "io.github.FlyJingFish.AndroidAop.android-aop" version "1.5.2" apply false } ``` @@ -138,12 +138,12 @@ plugins { dependencies { //Required items 👇 - implementation 'io.github.FlyJingFish.AndroidAop:android-aop-core:1.5.1' - implementation 'io.github.FlyJingFish.AndroidAop:android-aop-annotation:1.5.1' + implementation 'io.github.FlyJingFish.AndroidAop:android-aop-core:1.5.2' + implementation 'io.github.FlyJingFish.AndroidAop:android-aop-annotation:1.5.2' //Optional 👇, if you want to customize aspects, you need to use them, ⚠️supports aspects written in Java and Kotlin code - ksp 'io.github.FlyJingFish.AndroidAop:android-aop-ksp:1.5.1' + ksp 'io.github.FlyJingFish.AndroidAop:android-aop-ksp:1.5.2' //Optional 👇, if you want to customize aspects, you need to use them, ⚠️only applies to aspects written in Java code - annotationProcessor 'io.github.FlyJingFish.AndroidAop:android-aop-processor:1.5.1' + annotationProcessor 'io.github.FlyJingFish.AndroidAop:android-aop-processor:1.5.2' //⚠️Choose one of the above android-aop-ksp and android-aop-processor } ``` diff --git a/gradle.properties b/gradle.properties index 5e9ea343..b1210139 100644 --- a/gradle.properties +++ b/gradle.properties @@ -40,7 +40,7 @@ DEVELOPER_ID=FlyJingFish DEVELOPER_NAME=FlyJingFish DEVELOPER_EMAIL=749617782@qq.com -TestVersion = 1.5.1 +TestVersion = 1.5.2 SonatypeTestCode = 1395 TestType = 0 # 0 mavenLocal 1 SonatypeCache 2 mavenCentral diff --git a/version.properties b/version.properties index 9eda00d7..014bca50 100644 --- a/version.properties +++ b/version.properties @@ -1,2 +1,2 @@ -#Wed Apr 03 11:58:38 CST 2024 -PROJ_VERSION=1.5.1 +#Wed Apr 03 22:52:18 CST 2024 +PROJ_VERSION=1.5.2