From bf3ff30943d038a695f7ee890d4b7f369a5eea8c Mon Sep 17 00:00:00 2001 From: FlyJingFish Date: Sat, 10 Aug 2024 10:31:08 +0800 Subject: [PATCH 1/5] =?UTF-8?q?1=E3=80=81=E4=BC=98=E5=8C=96suspend?= =?UTF-8?q?=E5=87=BD=E6=95=B0=E5=88=87=E7=82=B9=E5=A4=84=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../scanner_visitor/SuspendReturnScanner.kt | 54 +++++++++++++++++++ .../tasks/AssembleAndroidAopTask.kt | 6 ++- .../tasks/CompileAndroidAopTask.kt | 5 +- .../android_aop_plugin/utils/AopTaskUtils.kt | 26 +++++++++ .../utils/WovenInfoUtils.kt | 18 ++++++- 5 files changed, 105 insertions(+), 4 deletions(-) create mode 100644 android-aop-plugin/src/main/kotlin/com/flyjingfish/android_aop_plugin/scanner_visitor/SuspendReturnScanner.kt diff --git a/android-aop-plugin/src/main/kotlin/com/flyjingfish/android_aop_plugin/scanner_visitor/SuspendReturnScanner.kt b/android-aop-plugin/src/main/kotlin/com/flyjingfish/android_aop_plugin/scanner_visitor/SuspendReturnScanner.kt new file mode 100644 index 00000000..0c71e7bd --- /dev/null +++ b/android-aop-plugin/src/main/kotlin/com/flyjingfish/android_aop_plugin/scanner_visitor/SuspendReturnScanner.kt @@ -0,0 +1,54 @@ +package com.flyjingfish.android_aop_plugin.scanner_visitor + +import org.objectweb.asm.ClassVisitor +import org.objectweb.asm.MethodVisitor +import org.objectweb.asm.Opcodes + +class SuspendReturnScanner : ClassVisitor(Opcodes.ASM9) { + companion object{ + var hasSuspendReturn = false + } + + private lateinit var className :String + override fun visit( + version: Int, + access: Int, + name: String, + signature: String?, + superName: String?, + interfaces: Array? + ) { + super.visit(version, access, name, signature, superName, interfaces) + className = name + } + + override fun visitMethod( + access: Int, + name: String, + descriptor: String, + signature: String?, + exceptions: Array? + ): MethodVisitor { + return ReplaceInvokeMethodVisitor() + } + + inner class ReplaceInvokeMethodVisitor : + MethodVisitor(Opcodes.ASM9) { + override fun visitMethodInsn( + opcode: Int, + owner: String, + name: String, + descriptor: String, + isInterface: Boolean + ) { + super.visitMethodInsn(opcode, owner, name, descriptor, isInterface) + if (owner == "com/flyjingfish/android_aop_annotation/ProceedJoinPointSuspend" + && ((name == "proceed" && (descriptor == "(Lcom/flyjingfish/android_aop_annotation/base/OnSuspendReturnListener;)Ljava/lang/Object;" + || descriptor == "(Lcom/flyjingfish/android_aop_annotation/base/OnSuspendReturnListener;[Ljava/lang/Object;)Ljava/lang/Object;")) + || (name == "proceedIgnoreOther" && (descriptor == "(Lcom/flyjingfish/android_aop_annotation/base/OnSuspendReturnListener2;)Ljava/lang/Object;" + || descriptor == "(Lcom/flyjingfish/android_aop_annotation/base/OnSuspendReturnListener2;[Ljava/lang/Object;)Ljava/lang/Object;")))){ + hasSuspendReturn = true + } + } + } +} \ No newline at end of file diff --git a/android-aop-plugin/src/main/kotlin/com/flyjingfish/android_aop_plugin/tasks/AssembleAndroidAopTask.kt b/android-aop-plugin/src/main/kotlin/com/flyjingfish/android_aop_plugin/tasks/AssembleAndroidAopTask.kt index fa735b99..ddf68ac0 100644 --- a/android-aop-plugin/src/main/kotlin/com/flyjingfish/android_aop_plugin/tasks/AssembleAndroidAopTask.kt +++ b/android-aop-plugin/src/main/kotlin/com/flyjingfish/android_aop_plugin/tasks/AssembleAndroidAopTask.kt @@ -6,6 +6,7 @@ import com.flyjingfish.android_aop_plugin.config.AndroidAopConfig import com.flyjingfish.android_aop_plugin.scanner_visitor.RegisterMapWovenInfoCode import com.flyjingfish.android_aop_plugin.scanner_visitor.ReplaceBaseClassVisitor import com.flyjingfish.android_aop_plugin.scanner_visitor.ReplaceInvokeMethodVisitor +import com.flyjingfish.android_aop_plugin.scanner_visitor.SuspendReturnScanner import com.flyjingfish.android_aop_plugin.scanner_visitor.WovenIntoCode import com.flyjingfish.android_aop_plugin.utils.AopTaskUtils import com.flyjingfish.android_aop_plugin.utils.ClassFileUtils @@ -70,6 +71,7 @@ abstract class AssembleAndroidAopTask : DefaultTask() { ClassFileUtils.outputDir = File(Utils.aopTransformTempDir(project,variant)) ClassFileUtils.clear() ClassFileUtils.outputDir.deleteRecursively() + SuspendReturnScanner.hasSuspendReturn = false jarOutput = JarOutputStream(BufferedOutputStream(FileOutputStream(output.get().asFile))) val scanTimeCost = measureTimeMillis { scanFile() @@ -212,7 +214,7 @@ abstract class AssembleAndroidAopTask : DefaultTask() { val methodsRecord: HashMap? = WovenInfoUtils.getClassMethodRecord(file.absolutePath) val isSuspend:Boolean - val realMethodsRecord: HashMap? = if (methodsRecord == null && isWovenInfoCode){ + val realMethodsRecord: HashMap? = if (methodsRecord == null && SuspendReturnScanner.hasSuspendReturn && isWovenInfoCode){ isSuspend = true val clazzName = entryName.replace(_CLASS,"") WovenInfoUtils.getAopMethodCutInnerClassInfoInvokeClassInfo(clazzName) @@ -456,7 +458,7 @@ abstract class AssembleAndroidAopTask : DefaultTask() { && !entryName.startsWith("kotlinx/") && !entryName.startsWith("kotlin/") val methodsRecord: HashMap? = WovenInfoUtils.getClassMethodRecord(entryName) val isSuspend:Boolean - val realMethodsRecord: HashMap? = if (methodsRecord == null && isWovenInfoCode){ + val realMethodsRecord: HashMap? = if (methodsRecord == null && SuspendReturnScanner.hasSuspendReturn && isWovenInfoCode){ isSuspend = true WovenInfoUtils.getAopMethodCutInnerClassInfoInvokeClassInfo(entryClazzName) }else { diff --git a/android-aop-plugin/src/main/kotlin/com/flyjingfish/android_aop_plugin/tasks/CompileAndroidAopTask.kt b/android-aop-plugin/src/main/kotlin/com/flyjingfish/android_aop_plugin/tasks/CompileAndroidAopTask.kt index b929fc4c..214b095a 100644 --- a/android-aop-plugin/src/main/kotlin/com/flyjingfish/android_aop_plugin/tasks/CompileAndroidAopTask.kt +++ b/android-aop-plugin/src/main/kotlin/com/flyjingfish/android_aop_plugin/tasks/CompileAndroidAopTask.kt @@ -6,6 +6,7 @@ import com.flyjingfish.android_aop_plugin.beans.TmpFile import com.flyjingfish.android_aop_plugin.config.AndroidAopConfig import com.flyjingfish.android_aop_plugin.scanner_visitor.ReplaceBaseClassVisitor import com.flyjingfish.android_aop_plugin.scanner_visitor.ReplaceInvokeMethodVisitor +import com.flyjingfish.android_aop_plugin.scanner_visitor.SuspendReturnScanner import com.flyjingfish.android_aop_plugin.scanner_visitor.WovenIntoCode import com.flyjingfish.android_aop_plugin.utils.AopTaskUtils import com.flyjingfish.android_aop_plugin.utils.ClassFileUtils @@ -15,6 +16,7 @@ import com.flyjingfish.android_aop_plugin.utils.Utils._CLASS import com.flyjingfish.android_aop_plugin.utils.WovenInfoUtils import com.flyjingfish.android_aop_plugin.utils.checkExist import com.flyjingfish.android_aop_plugin.utils.inRules +import com.flyjingfish.android_aop_plugin.utils.printLog import com.flyjingfish.android_aop_plugin.utils.saveEntry import com.flyjingfish.android_aop_plugin.utils.saveFile import org.gradle.api.Project @@ -47,6 +49,7 @@ class CompileAndroidAopTask( ClassFileUtils.outputDir = output ClassFileUtils.outputCacheDir = File(Utils.aopCompileTempInvokeDir(project, variantName)) ClassFileUtils.clear() + SuspendReturnScanner.hasSuspendReturn = false println("AndroidAOP woven info code start") val scanTimeCost = measureTimeMillis { scanFile() @@ -122,7 +125,7 @@ class CompileAndroidAopTask( val methodsRecord: HashMap? = WovenInfoUtils.getClassMethodRecord(file.absolutePath) val isSuspend:Boolean - val realMethodsRecord: HashMap? = if (methodsRecord == null && isWovenInfoCode){ + val realMethodsRecord: HashMap? = if (methodsRecord == null && SuspendReturnScanner.hasSuspendReturn && isWovenInfoCode){ isSuspend = true val clazzName = entryName.replace(_CLASS,"") WovenInfoUtils.getAopMethodCutInnerClassInfoInvokeClassInfo(clazzName) diff --git a/android-aop-plugin/src/main/kotlin/com/flyjingfish/android_aop_plugin/utils/AopTaskUtils.kt b/android-aop-plugin/src/main/kotlin/com/flyjingfish/android_aop_plugin/utils/AopTaskUtils.kt index 374c10b3..fb096ed3 100644 --- a/android-aop-plugin/src/main/kotlin/com/flyjingfish/android_aop_plugin/utils/AopTaskUtils.kt +++ b/android-aop-plugin/src/main/kotlin/com/flyjingfish/android_aop_plugin/utils/AopTaskUtils.kt @@ -10,6 +10,7 @@ import com.flyjingfish.android_aop_plugin.scanner_visitor.MethodReplaceInvokeVis import com.flyjingfish.android_aop_plugin.scanner_visitor.ReplaceBaseClassVisitor import com.flyjingfish.android_aop_plugin.scanner_visitor.SearchAOPConfigVisitor import com.flyjingfish.android_aop_plugin.scanner_visitor.SearchAopMethodVisitor +import com.flyjingfish.android_aop_plugin.scanner_visitor.SuspendReturnScanner import com.flyjingfish.android_aop_plugin.scanner_visitor.WovenIntoCode import org.gradle.api.Project import org.objectweb.asm.ClassReader @@ -176,6 +177,19 @@ object AopTaskUtils { if (file.absolutePath.endsWith(Utils._CLASS)){ val className = file.absolutePath.replace("$directoryPath/","").replace(".class","") WovenInfoUtils.addExtendsReplace(Utils.slashToDot(className)) + + val isAopCutClass = WovenInfoUtils.isAopMethodCutClass(className) || WovenInfoUtils.isAopMatchCutClass(className) + if (isAopCutClass){ + FileInputStream(file).use { inputs -> + val bytes = inputs.readAllBytes() + if (bytes.isNotEmpty()){ + val classReader = ClassReader(bytes) + classReader.accept( + SuspendReturnScanner(), 0) + } + } + } + } } @@ -231,6 +245,18 @@ object AopTaskUtils { if (entryName.endsWith(Utils._CLASS)){ val className = entryName.replace(".class","") WovenInfoUtils.addExtendsReplace(Utils.slashToDot(className)) + + val isAopCutClass = WovenInfoUtils.isAopMethodCutClass(className) || WovenInfoUtils.isAopMatchCutClass(className) + if (isAopCutClass){ + jarFile.getInputStream(jarEntry).use { inputs -> + val bytes = inputs.readAllBytes() + if (bytes.isNotEmpty()){ + val classReader = ClassReader(bytes) + classReader.accept( + SuspendReturnScanner(), 0) + } + } + } } } catch (e: Exception) { printLog("Merge jar error entry:[${jarEntry.name}], error message:$e") diff --git a/android-aop-plugin/src/main/kotlin/com/flyjingfish/android_aop_plugin/utils/WovenInfoUtils.kt b/android-aop-plugin/src/main/kotlin/com/flyjingfish/android_aop_plugin/utils/WovenInfoUtils.kt index 30edfd6d..11d10092 100644 --- a/android-aop-plugin/src/main/kotlin/com/flyjingfish/android_aop_plugin/utils/WovenInfoUtils.kt +++ b/android-aop-plugin/src/main/kotlin/com/flyjingfish/android_aop_plugin/utils/WovenInfoUtils.kt @@ -132,6 +132,15 @@ object WovenInfoUtils { aopMethodCuts[info.anno] = info } + fun isAopMethodCutClass(className: String):Boolean{ + for (aopMethodCut in aopMethodCuts) { + if (Utils.slashToDotClassName(className).contains(aopMethodCut.value.cutClassName)){ + return true + } + } + return false + } + fun addAopInstance(key: String,className: String) { aopInstances[key] = className } @@ -150,7 +159,14 @@ object WovenInfoUtils { //baseClassName -> cutClassName 防止被覆盖 aopMatchCuts[info.cutClassName] = info } - + fun isAopMatchCutClass(className: String):Boolean{ + for (aopMatchCut in aopMatchCuts) { + if (aopMatchCut.key.contains(Utils.slashToDotClassName(className))){ + return true + } + } + return false + } fun addClassMethodRecords(classMethodRecord: ClassMethodRecord) { var methodsRecord: HashMap? = classMethodRecords[classMethodRecord.classFile] From 95e897146ac9a763d9f795fd47431ae12875548b Mon Sep 17 00:00:00 2001 From: tianxiangyu <96164429+FlyJingFish@users.noreply.github.com> Date: Tue, 13 Aug 2024 17:01:37 +0800 Subject: [PATCH 2/5] =?UTF-8?q?1=E3=80=81=E6=96=B0=E5=A2=9E=E6=94=AF?= =?UTF-8?q?=E6=8C=81=E6=9B=BF=E6=8D=A2=E8=B0=83=E7=94=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../beans/ReplaceMethodInfo.kt | 3 ++- .../MethodReplaceInvokeAdapter.kt | 20 ++++++++++---- .../MethodReplaceInvokeVisitor.kt | 4 ++- .../scanner_visitor/SearchAopMethodVisitor.kt | 26 +++++++++++++++++-- .../scanner_visitor/WovenIntoCode.kt | 2 +- .../flyjingfish/androidaop/MainActivity.kt | 4 ++- .../flyjingfish/androidaop/ReplaceTestBean.kt | 7 +++++ .../flyjingfish/test_lib/ReplaceTestMatch.kt | 24 +++++++++++++++++ .../com/flyjingfish/test_lib/TestMatch.java | 11 +++++++- .../com/flyjingfish/test_lib/TestMatch2.java | 11 ++++++++ 10 files changed, 100 insertions(+), 12 deletions(-) create mode 100644 test-lib/src/main/java/com/flyjingfish/test_lib/ReplaceTestMatch.kt create mode 100644 test-lib/src/main/java/com/flyjingfish/test_lib/TestMatch2.java diff --git a/android-aop-plugin/src/main/kotlin/com/flyjingfish/android_aop_plugin/beans/ReplaceMethodInfo.kt b/android-aop-plugin/src/main/kotlin/com/flyjingfish/android_aop_plugin/beans/ReplaceMethodInfo.kt index ce1c6cda..20f0ae61 100644 --- a/android-aop-plugin/src/main/kotlin/com/flyjingfish/android_aop_plugin/beans/ReplaceMethodInfo.kt +++ b/android-aop-plugin/src/main/kotlin/com/flyjingfish/android_aop_plugin/beans/ReplaceMethodInfo.kt @@ -6,7 +6,8 @@ data class ReplaceMethodInfo( var oldMethodDesc: String, var newOwner: String, var newMethodName: String, - var newMethodDesc: String + var newMethodDesc: String, + var isConstructor:Boolean = false ){ fun getReplaceKey():String{ return oldOwner + oldMethodName + oldMethodDesc diff --git a/android-aop-plugin/src/main/kotlin/com/flyjingfish/android_aop_plugin/scanner_visitor/MethodReplaceInvokeAdapter.kt b/android-aop-plugin/src/main/kotlin/com/flyjingfish/android_aop_plugin/scanner_visitor/MethodReplaceInvokeAdapter.kt index 2f1d062f..49805105 100644 --- a/android-aop-plugin/src/main/kotlin/com/flyjingfish/android_aop_plugin/scanner_visitor/MethodReplaceInvokeAdapter.kt +++ b/android-aop-plugin/src/main/kotlin/com/flyjingfish/android_aop_plugin/scanner_visitor/MethodReplaceInvokeAdapter.kt @@ -6,9 +6,10 @@ import org.objectweb.asm.MethodVisitor import org.objectweb.asm.Opcodes -class MethodReplaceInvokeAdapter(private val className:String, +class MethodReplaceInvokeAdapter(private val className:String,private val superName: String, private val methodNameDesc:String, methodVisitor: MethodVisitor?) : MethodVisitor(Opcodes.ASM9, methodVisitor) { + val isConstructorMethod = methodNameDesc.startsWith("(") interface OnResultListener{ fun onBack() @@ -36,12 +37,21 @@ class MethodReplaceInvokeAdapter(private val className:String, } if (isReplaceClass && replaceMethodInfo != null && (!className.contains(replaceMethodInfo.newOwner) || methodNameDesc != "${replaceMethodInfo.newMethodName}${replaceMethodInfo.newMethodDesc}")) { - val shouldReplaceDesc: String = if (opcode == Opcodes.INVOKESTATIC) { - descriptor + val shouldReplace: Boolean = if (replaceMethodInfo.isConstructor) { + if (isConstructorMethod){ + !(owner == superName && name == "") + }else{ + descriptor == replaceMethodInfo.oldMethodDesc + } + } else if (opcode == Opcodes.INVOKESTATIC) { + descriptor == replaceMethodInfo.newMethodDesc } else { - descriptor.replace("(", "(L${replaceMethodInfo.oldOwner};") + descriptor.replace("(", "(L${replaceMethodInfo.oldOwner};") == replaceMethodInfo.newMethodDesc } - if (shouldReplaceDesc == replaceMethodInfo.newMethodDesc) { + if (shouldReplace) { + if (replaceMethodInfo.isConstructor) { + super.visitMethodInsn(opcode, owner, name, descriptor, isInterface) + } InitConfig.addReplaceMethodInfo(replaceMethodInfo) // 注意,最后一个参数是false,会不会太武断呢? super.visitMethodInsn( diff --git a/android-aop-plugin/src/main/kotlin/com/flyjingfish/android_aop_plugin/scanner_visitor/MethodReplaceInvokeVisitor.kt b/android-aop-plugin/src/main/kotlin/com/flyjingfish/android_aop_plugin/scanner_visitor/MethodReplaceInvokeVisitor.kt index 4dc87060..a95d6621 100644 --- a/android-aop-plugin/src/main/kotlin/com/flyjingfish/android_aop_plugin/scanner_visitor/MethodReplaceInvokeVisitor.kt +++ b/android-aop-plugin/src/main/kotlin/com/flyjingfish/android_aop_plugin/scanner_visitor/MethodReplaceInvokeVisitor.kt @@ -8,6 +8,7 @@ open class MethodReplaceInvokeVisitor( classVisitor: ClassVisitor ) : ReplaceBaseClassVisitor(classVisitor) { lateinit var className: String + lateinit var superName: String var replaced = false override fun visit( version: Int, @@ -19,6 +20,7 @@ open class MethodReplaceInvokeVisitor( ) { super.visit(version, access, name, signature, superName, interfaces) className = name + this.superName = superName } override fun visitMethod( access: Int, @@ -30,7 +32,7 @@ open class MethodReplaceInvokeVisitor( var mv: MethodVisitor? = super.visitMethod(access, name, descriptor, signature, exceptions) if (mv != null && access.isHasMethodBody()) { - mv = MethodReplaceInvokeAdapter(className,"$name$descriptor",mv) + mv = MethodReplaceInvokeAdapter(className,superName,"$name$descriptor",mv) mv.onResultListener = object : MethodReplaceInvokeAdapter.OnResultListener{ override fun onBack() { replaced = true diff --git a/android-aop-plugin/src/main/kotlin/com/flyjingfish/android_aop_plugin/scanner_visitor/SearchAopMethodVisitor.kt b/android-aop-plugin/src/main/kotlin/com/flyjingfish/android_aop_plugin/scanner_visitor/SearchAopMethodVisitor.kt index d96bbbd1..9f286ae0 100644 --- a/android-aop-plugin/src/main/kotlin/com/flyjingfish/android_aop_plugin/scanner_visitor/SearchAopMethodVisitor.kt +++ b/android-aop-plugin/src/main/kotlin/com/flyjingfish/android_aop_plugin/scanner_visitor/SearchAopMethodVisitor.kt @@ -255,6 +255,7 @@ class SearchAopMethodVisitor(val onCallBackMethod: OnCallBackMethod?) : companion object { const val REPLACE_POINT = "Lcom/flyjingfish/android_aop_annotation/anno/AndroidAopReplaceMethod" + val initClassnamePattern = Pattern.compile("\\(.*?\\)") } open inner class MyMethodVisitor ( @@ -314,7 +315,15 @@ class SearchAopMethodVisitor(val onCallBackMethod: OnCallBackMethod?) : val name = methodname if (!name.isNullOrEmpty()){ try { - val methodInfo = getMethodInfo(name) + val fanMatcher = initClassnamePattern.matcher(name) + val newName = if (name.startsWith("") && fanMatcher.find()){ + replaceMethodInfo.isConstructor = true + "void $name" + }else{ + name + } + + val methodInfo = getMethodInfo(newName) if (methodInfo != null && methodInfo.checkAvailable()){ val methodText = methodInfo.returnType + " " + methodInfo.name + methodInfo.paramTypes @@ -322,7 +331,20 @@ class SearchAopMethodVisitor(val onCallBackMethod: OnCallBackMethod?) : replaceMethodInfo.oldMethodName = method.name replaceMethodInfo.oldMethodDesc = method.descriptor if (replaceMethodInfo.checkAvailable()){ - onCallBackMethod?.onBackReplaceMethodInfo(replaceMethodInfo) + if (replaceMethodInfo.isConstructor){ + val returnType = Type.getReturnType(replaceMethodInfo.newMethodDesc) + val returnTypeClassName = returnType.descriptor + val paramsTypes = Type.getArgumentTypes(replaceMethodInfo.newMethodDesc) + val paramType0 : Type? = if (paramsTypes.size == 1){ + paramsTypes[0] + }else null + + if (returnTypeClassName.startsWith("L") && returnTypeClassName.endsWith(";") && paramType0?.className == slashToDotClassName(replaceMethodInfo.oldOwner)){ + onCallBackMethod?.onBackReplaceMethodInfo(replaceMethodInfo) + } + }else{ + onCallBackMethod?.onBackReplaceMethodInfo(replaceMethodInfo) + } } } diff --git a/android-aop-plugin/src/main/kotlin/com/flyjingfish/android_aop_plugin/scanner_visitor/WovenIntoCode.kt b/android-aop-plugin/src/main/kotlin/com/flyjingfish/android_aop_plugin/scanner_visitor/WovenIntoCode.kt index 155ebb44..6c798754 100644 --- a/android-aop-plugin/src/main/kotlin/com/flyjingfish/android_aop_plugin/scanner_visitor/WovenIntoCode.kt +++ b/android-aop-plugin/src/main/kotlin/com/flyjingfish/android_aop_plugin/scanner_visitor/WovenIntoCode.kt @@ -249,7 +249,7 @@ object WovenIntoCode { ) if (hasReplace && mv != null && access.isHasMethodBody()) { - mv = MethodReplaceInvokeAdapter(className,"$name$descriptor",mv) + mv = MethodReplaceInvokeAdapter(className,oldSuperName,"$name$descriptor",mv) } WovenInfoUtils.addAopMethodCutInnerClassInfoInvokeMethod(className,newMethodName,descriptor) RemoveAnnotation(mv) diff --git a/app/src/main/java/com/flyjingfish/androidaop/MainActivity.kt b/app/src/main/java/com/flyjingfish/androidaop/MainActivity.kt index 7bef8cb8..75269b83 100644 --- a/app/src/main/java/com/flyjingfish/androidaop/MainActivity.kt +++ b/app/src/main/java/com/flyjingfish/androidaop/MainActivity.kt @@ -29,6 +29,7 @@ import com.flyjingfish.test_lib.annotation.MyAnno3 import com.flyjingfish.test_lib.BaseActivity import com.flyjingfish.test_lib.PermissionRejectListener import com.flyjingfish.test_lib.TestMatch +import com.flyjingfish.test_lib.TestMatch2 import com.flyjingfish.test_lib.annotation.MyAnno2 import com.flyjingfish.test_lib.mycut.TestParams2 import kotlinx.coroutines.Dispatchers @@ -133,7 +134,8 @@ class MainActivity: BaseActivity2(), PermissionRejectListener{ 11,12,13,15,15,16,17,18,19,20) } - val testMatch = TestMatch() + TestMatch2(1).test1() + TestMatch2().test1() binding.btnTestMuch.setOnClickListener { // testMatch.test2(1,"2") // diff --git a/app/src/main/java/com/flyjingfish/androidaop/ReplaceTestBean.kt b/app/src/main/java/com/flyjingfish/androidaop/ReplaceTestBean.kt index b9cf6f22..4da9f06e 100644 --- a/app/src/main/java/com/flyjingfish/androidaop/ReplaceTestBean.kt +++ b/app/src/main/java/com/flyjingfish/androidaop/ReplaceTestBean.kt @@ -7,6 +7,13 @@ import com.flyjingfish.androidaop.test.TestBean @AndroidAopReplaceClass("com.flyjingfish.androidaop.test.TestBean") object ReplaceTestBean { + + @AndroidAopReplaceMethod("()") + @JvmStatic + fun getTestBean(testBean: TestBean) : TestBean{ + return TestBean() + } + @AndroidAopReplaceMethod("void setName(java.lang.String)") @JvmStatic fun setName(testBean: TestBean, name: String) { diff --git a/test-lib/src/main/java/com/flyjingfish/test_lib/ReplaceTestMatch.kt b/test-lib/src/main/java/com/flyjingfish/test_lib/ReplaceTestMatch.kt new file mode 100644 index 00000000..6e009e29 --- /dev/null +++ b/test-lib/src/main/java/com/flyjingfish/test_lib/ReplaceTestMatch.kt @@ -0,0 +1,24 @@ +package com.flyjingfish.test_lib + +import android.util.Log +import com.flyjingfish.android_aop_annotation.anno.AndroidAopReplaceClass +import com.flyjingfish.android_aop_annotation.anno.AndroidAopReplaceMethod +import com.flyjingfish.android_aop_annotation.enums.MatchType +import com.flyjingfish.test_lib.TestMatch + +@AndroidAopReplaceClass(value = "com.flyjingfish.test_lib.TestMatch",type = MatchType.EXTENDS) +object ReplaceTestMatch { + + @AndroidAopReplaceMethod("(int)") + @JvmStatic + fun getTestBean(testBean: TestMatch) : TestMatch{ + return TestMatch(2) + } + + @AndroidAopReplaceMethod("void test1()") + @JvmStatic + fun test1(testBean: TestMatch) { + Log.e("test1","ReplaceTestMatch==label="+testBean.label) + } + +} \ No newline at end of file diff --git a/test-lib/src/main/java/com/flyjingfish/test_lib/TestMatch.java b/test-lib/src/main/java/com/flyjingfish/test_lib/TestMatch.java index 09f5cf62..9709dd9c 100644 --- a/test-lib/src/main/java/com/flyjingfish/test_lib/TestMatch.java +++ b/test-lib/src/main/java/com/flyjingfish/test_lib/TestMatch.java @@ -7,8 +7,17 @@ import com.flyjingfish.test_lib.annotation.MyAnno; public class TestMatch{ - public void test1(){ + public int label = 0; + + public TestMatch() { + } + public TestMatch(int label) { + this.label = label; + } + + public void test1(){ + Log.e("test1","label="+label); } public void test2(){ diff --git a/test-lib/src/main/java/com/flyjingfish/test_lib/TestMatch2.java b/test-lib/src/main/java/com/flyjingfish/test_lib/TestMatch2.java new file mode 100644 index 00000000..76a5c625 --- /dev/null +++ b/test-lib/src/main/java/com/flyjingfish/test_lib/TestMatch2.java @@ -0,0 +1,11 @@ +package com.flyjingfish.test_lib; + + +public class TestMatch2 extends TestMatch{ + public TestMatch2() { + } + + public TestMatch2(int label) { + super(label); + } +} From 371f1118636b534325014d311d8df567feeee10d Mon Sep 17 00:00:00 2001 From: tianxiangyu <96164429+FlyJingFish@users.noreply.github.com> Date: Tue, 13 Aug 2024 19:00:57 +0800 Subject: [PATCH 3/5] =?UTF-8?q?1=E3=80=81=E6=96=B0=E5=A2=9E=E6=94=AF?= =?UTF-8?q?=E6=8C=81=E6=9B=BF=E6=8D=A2=E8=B0=83=E7=94=A8=20new?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../anno/AndroidAopReplaceNew.kt | 15 +++++++ .../AndroidAopSymbolProcessor.kt | 41 ++++++++++++++++++- .../beans/ReplaceMethodInfo.kt | 24 ++++++++++- .../MethodReplaceInvokeAdapter.kt | 27 +++++++----- .../scanner_visitor/SearchAopMethodVisitor.kt | 25 +++++++++-- .../AndroidAopProcessor.java | 10 +++-- .../flyjingfish/androidaop/MainActivity.kt | 1 - .../flyjingfish/test_lib/ReplaceTestMatch.kt | 5 +++ .../com/flyjingfish/test_lib/TestMatch3.java | 13 ++++++ 9 files changed, 141 insertions(+), 20 deletions(-) create mode 100644 android-aop-annotation/src/main/java/com/flyjingfish/android_aop_annotation/anno/AndroidAopReplaceNew.kt create mode 100644 test-lib/src/main/java/com/flyjingfish/test_lib/TestMatch3.java diff --git a/android-aop-annotation/src/main/java/com/flyjingfish/android_aop_annotation/anno/AndroidAopReplaceNew.kt b/android-aop-annotation/src/main/java/com/flyjingfish/android_aop_annotation/anno/AndroidAopReplaceNew.kt new file mode 100644 index 00000000..bab8c201 --- /dev/null +++ b/android-aop-annotation/src/main/java/com/flyjingfish/android_aop_annotation/anno/AndroidAopReplaceNew.kt @@ -0,0 +1,15 @@ +package com.flyjingfish.android_aop_annotation.anno + +/** + * 定义替换类的构造方法调用的注解,此注解用在替换类的 + * [wiki 文档使用说明](https://github.com/FlyJingFish/AndroidAOP/wiki/@AndroidAopReplaceConstructor) + */ +@Target( + AnnotationTarget.FUNCTION, + AnnotationTarget.PROPERTY_GETTER, + AnnotationTarget.PROPERTY_SETTER +) +@Retention(AnnotationRetention.BINARY) +annotation class AndroidAopReplaceNew( + val value: String +) diff --git a/android-aop-ksp/src/main/java/com/flyjingfish/android_aop_ksp/AndroidAopSymbolProcessor.kt b/android-aop-ksp/src/main/java/com/flyjingfish/android_aop_ksp/AndroidAopSymbolProcessor.kt index a54e426b..cd556360 100644 --- a/android-aop-ksp/src/main/java/com/flyjingfish/android_aop_ksp/AndroidAopSymbolProcessor.kt +++ b/android-aop-ksp/src/main/java/com/flyjingfish/android_aop_ksp/AndroidAopSymbolProcessor.kt @@ -5,6 +5,7 @@ import com.flyjingfish.android_aop_annotation.anno.AndroidAopModifyExtendsClass import com.flyjingfish.android_aop_annotation.anno.AndroidAopPointCut import com.flyjingfish.android_aop_annotation.anno.AndroidAopReplaceClass import com.flyjingfish.android_aop_annotation.anno.AndroidAopReplaceMethod +import com.flyjingfish.android_aop_annotation.anno.AndroidAopReplaceNew import com.flyjingfish.android_aop_annotation.aop_anno.AopClass import com.flyjingfish.android_aop_annotation.aop_anno.AopCollectMethod import com.flyjingfish.android_aop_annotation.aop_anno.AopMatchClassMethod @@ -68,7 +69,8 @@ class AndroidAopSymbolProcessor(private val codeGenerator: CodeGenerator, // logger.error("---------AndroidAopSymbolProcessor---------") val ret1 = processPointCut(resolver) val ret2 = processMatch(resolver) - processReplaceMethod(resolver) + processReplaceMethod(resolver,AndroidAopReplaceMethod::class.qualifiedName!!) + processReplaceMethod(resolver,AndroidAopReplaceNew::class.qualifiedName!!) val ret3 = processReplace(resolver) val ret4 = processModifyExtendsClass(resolver) val ret5 = processCollectMethod(resolver) @@ -378,7 +380,41 @@ class AndroidAopSymbolProcessor(private val codeGenerator: CodeGenerator, return symbols.filter { !it.validate() }.toList() } - private fun processReplaceMethod(resolver: Resolver): List { + private fun processReplaceMethod(resolver: Resolver,qualifiedName :String): List { + val symbols :Sequence = + resolver.getSymbolsWithAnnotation(qualifiedName) + for (symbol in symbols) { + val annotationMap = getAnnotation(symbol) + + if (symbol.origin == Origin.KOTLIN){ + if (!annotationMap.containsKey("@JvmStatic")){ + var className = "${(symbol as KSFunctionDeclaration).packageName.asString()}." + var parent = symbol.parent + while (parent !is KSFile){ + className = "$className$parent." + parent = parent?.parent + } + throw IllegalArgumentException("注意:函数$className${symbol} 必须添加 @JvmStatic 注解") + } + + }else if (symbol.origin == Origin.JAVA){ + if (symbol is KSFunctionDeclaration){ + if (symbol.functionKind != FunctionKind.STATIC){ + var className = "${symbol.packageName.asString()}." + var parent = symbol.parent + while (parent !is KSFile){ + className = "$className$parent." + parent = parent?.parent + } + throw IllegalArgumentException("注意:方法$className${symbol} 必须是静态方法") + } + } + } + } + return symbols.filter { !it.validate() }.toList() + } + + private fun processReplaceNew(resolver: Resolver): List { val symbols :Sequence = resolver.getSymbolsWithAnnotation(AndroidAopReplaceMethod::class.qualifiedName!!) for (symbol in symbols) { @@ -412,6 +448,7 @@ class AndroidAopSymbolProcessor(private val codeGenerator: CodeGenerator, return symbols.filter { !it.validate() }.toList() } + private fun processModifyExtendsClass(resolver: Resolver): List { val symbols :Sequence = resolver.getSymbolsWithAnnotation(AndroidAopModifyExtendsClass::class.qualifiedName!!) diff --git a/android-aop-plugin/src/main/kotlin/com/flyjingfish/android_aop_plugin/beans/ReplaceMethodInfo.kt b/android-aop-plugin/src/main/kotlin/com/flyjingfish/android_aop_plugin/beans/ReplaceMethodInfo.kt index 20f0ae61..bc352ce8 100644 --- a/android-aop-plugin/src/main/kotlin/com/flyjingfish/android_aop_plugin/beans/ReplaceMethodInfo.kt +++ b/android-aop-plugin/src/main/kotlin/com/flyjingfish/android_aop_plugin/beans/ReplaceMethodInfo.kt @@ -1,5 +1,7 @@ package com.flyjingfish.android_aop_plugin.beans +import org.objectweb.asm.Type + data class ReplaceMethodInfo( var oldOwner: String, var oldMethodName: String, @@ -7,8 +9,13 @@ data class ReplaceMethodInfo( var newOwner: String, var newMethodName: String, var newMethodDesc: String, - var isConstructor:Boolean = false + var replaceType:ReplaceType = ReplaceType.METHOD, + var newClassName :String = "" ){ + private var isCallNew:Boolean?=null + enum class ReplaceType{ + METHOD,INIT,NEW + } fun getReplaceKey():String{ return oldOwner + oldMethodName + oldMethodDesc } @@ -19,4 +26,19 @@ data class ReplaceMethodInfo( return oldOwner.isNotEmpty() && oldMethodName.isNotEmpty() && oldMethodDesc.isNotEmpty() && newOwner.isNotEmpty() && newMethodName.isNotEmpty() && newMethodDesc.isNotEmpty() } + + fun isCallNew():Boolean{ + val oldCallNew = isCallNew + if (oldCallNew != null){ + return oldCallNew + } + val callNew = if (replaceType == ReplaceType.NEW){ + val type = Type.getReturnType(newMethodDesc) + type.descriptor != "V" + }else{ + false + } + isCallNew = callNew + return callNew + } } \ No newline at end of file diff --git a/android-aop-plugin/src/main/kotlin/com/flyjingfish/android_aop_plugin/scanner_visitor/MethodReplaceInvokeAdapter.kt b/android-aop-plugin/src/main/kotlin/com/flyjingfish/android_aop_plugin/scanner_visitor/MethodReplaceInvokeAdapter.kt index 49805105..545a0ace 100644 --- a/android-aop-plugin/src/main/kotlin/com/flyjingfish/android_aop_plugin/scanner_visitor/MethodReplaceInvokeAdapter.kt +++ b/android-aop-plugin/src/main/kotlin/com/flyjingfish/android_aop_plugin/scanner_visitor/MethodReplaceInvokeAdapter.kt @@ -1,5 +1,6 @@ package com.flyjingfish.android_aop_plugin.scanner_visitor +import com.flyjingfish.android_aop_plugin.beans.ReplaceMethodInfo import com.flyjingfish.android_aop_plugin.utils.InitConfig import com.flyjingfish.android_aop_plugin.utils.WovenInfoUtils import org.objectweb.asm.MethodVisitor @@ -37,7 +38,7 @@ class MethodReplaceInvokeAdapter(private val className:String,private val superN } if (isReplaceClass && replaceMethodInfo != null && (!className.contains(replaceMethodInfo.newOwner) || methodNameDesc != "${replaceMethodInfo.newMethodName}${replaceMethodInfo.newMethodDesc}")) { - val shouldReplace: Boolean = if (replaceMethodInfo.isConstructor) { + val shouldReplace: Boolean = if (replaceMethodInfo.replaceType == ReplaceMethodInfo.ReplaceType.INIT||replaceMethodInfo.replaceType == ReplaceMethodInfo.ReplaceType.NEW) { if (isConstructorMethod){ !(owner == superName && name == "") }else{ @@ -49,18 +50,24 @@ class MethodReplaceInvokeAdapter(private val className:String,private val superN descriptor.replace("(", "(L${replaceMethodInfo.oldOwner};") == replaceMethodInfo.newMethodDesc } if (shouldReplace) { - if (replaceMethodInfo.isConstructor) { + if (replaceMethodInfo.replaceType == ReplaceMethodInfo.ReplaceType.INIT) { super.visitMethodInsn(opcode, owner, name, descriptor, isInterface) + }else if (replaceMethodInfo.replaceType == ReplaceMethodInfo.ReplaceType.NEW && replaceMethodInfo.isCallNew()) { + super.visitMethodInsn(opcode, replaceMethodInfo.newClassName, name, descriptor, isInterface) } InitConfig.addReplaceMethodInfo(replaceMethodInfo) - // 注意,最后一个参数是false,会不会太武断呢? - super.visitMethodInsn( - Opcodes.INVOKESTATIC, - replaceMethodInfo.newOwner, - replaceMethodInfo.newMethodName, - replaceMethodInfo.newMethodDesc, - false - ) + if (replaceMethodInfo.replaceType == ReplaceMethodInfo.ReplaceType.NEW && !replaceMethodInfo.isCallNew()){ + super.visitMethodInsn(opcode, replaceMethodInfo.newClassName, name, descriptor, isInterface) + }else{ + // 注意,最后一个参数是false,会不会太武断呢? + super.visitMethodInsn( + Opcodes.INVOKESTATIC, + replaceMethodInfo.newOwner, + replaceMethodInfo.newMethodName, + replaceMethodInfo.newMethodDesc, + false + ) + } onResultListener?.onBack() } else { super.visitMethodInsn(opcode, owner, name, descriptor, isInterface) diff --git a/android-aop-plugin/src/main/kotlin/com/flyjingfish/android_aop_plugin/scanner_visitor/SearchAopMethodVisitor.kt b/android-aop-plugin/src/main/kotlin/com/flyjingfish/android_aop_plugin/scanner_visitor/SearchAopMethodVisitor.kt index 9f286ae0..28bde5cb 100644 --- a/android-aop-plugin/src/main/kotlin/com/flyjingfish/android_aop_plugin/scanner_visitor/SearchAopMethodVisitor.kt +++ b/android-aop-plugin/src/main/kotlin/com/flyjingfish/android_aop_plugin/scanner_visitor/SearchAopMethodVisitor.kt @@ -255,6 +255,8 @@ class SearchAopMethodVisitor(val onCallBackMethod: OnCallBackMethod?) : companion object { const val REPLACE_POINT = "Lcom/flyjingfish/android_aop_annotation/anno/AndroidAopReplaceMethod" + const val NEW_POINT = + "Lcom/flyjingfish/android_aop_annotation/anno/AndroidAopReplaceNew" val initClassnamePattern = Pattern.compile("\\(.*?\\)") } open inner class MyMethodVisitor @@ -289,12 +291,15 @@ class SearchAopMethodVisitor(val onCallBackMethod: OnCallBackMethod?) : } } - if (descriptor.contains(REPLACE_POINT) && replaceTargetClassName != null && access.isStaticMethod()){ + if ((descriptor.contains(REPLACE_POINT) || descriptor.contains(NEW_POINT)) && replaceTargetClassName != null && access.isStaticMethod()){ val replaceMethodInfo = ReplaceMethodInfo( replaceTargetClassName!!,"","", className,methodname,methoddescriptor ) + if (descriptor.contains(NEW_POINT)){ + replaceMethodInfo.replaceType = ReplaceMethodInfo.ReplaceType.NEW + } return ReplaceMethodVisitor(replaceMethodInfo) } return super.visitAnnotation(descriptor, visible) @@ -317,7 +322,9 @@ class SearchAopMethodVisitor(val onCallBackMethod: OnCallBackMethod?) : try { val fanMatcher = initClassnamePattern.matcher(name) val newName = if (name.startsWith("") && fanMatcher.find()){ - replaceMethodInfo.isConstructor = true + if (replaceMethodInfo.replaceType == ReplaceMethodInfo.ReplaceType.METHOD){ + replaceMethodInfo.replaceType = ReplaceMethodInfo.ReplaceType.INIT + } "void $name" }else{ name @@ -331,7 +338,7 @@ class SearchAopMethodVisitor(val onCallBackMethod: OnCallBackMethod?) : replaceMethodInfo.oldMethodName = method.name replaceMethodInfo.oldMethodDesc = method.descriptor if (replaceMethodInfo.checkAvailable()){ - if (replaceMethodInfo.isConstructor){ + if (replaceMethodInfo.replaceType == ReplaceMethodInfo.ReplaceType.INIT){ val returnType = Type.getReturnType(replaceMethodInfo.newMethodDesc) val returnTypeClassName = returnType.descriptor val paramsTypes = Type.getArgumentTypes(replaceMethodInfo.newMethodDesc) @@ -342,6 +349,18 @@ class SearchAopMethodVisitor(val onCallBackMethod: OnCallBackMethod?) : if (returnTypeClassName.startsWith("L") && returnTypeClassName.endsWith(";") && paramType0?.className == slashToDotClassName(replaceMethodInfo.oldOwner)){ onCallBackMethod?.onBackReplaceMethodInfo(replaceMethodInfo) } + }else if (replaceMethodInfo.replaceType == ReplaceMethodInfo.ReplaceType.NEW){ + val paramsTypes = Type.getArgumentTypes(replaceMethodInfo.newMethodDesc) + val paramType0 : Type? = if (paramsTypes.size == 1){ + paramsTypes[0] + }else null + + val paramType0ClassName = paramType0?.descriptor ?:"" + + if (paramType0ClassName.startsWith("L") && paramType0ClassName.endsWith(";")){ + replaceMethodInfo.newClassName = paramType0ClassName.substring(1,paramType0ClassName.length - 1) + onCallBackMethod?.onBackReplaceMethodInfo(replaceMethodInfo) + } }else{ onCallBackMethod?.onBackReplaceMethodInfo(replaceMethodInfo) } diff --git a/android-aop-processor/src/main/java/com/flyjingfish/android_aop_processor/AndroidAopProcessor.java b/android-aop-processor/src/main/java/com/flyjingfish/android_aop_processor/AndroidAopProcessor.java index 5db6fe4a..604cc050 100644 --- a/android-aop-processor/src/main/java/com/flyjingfish/android_aop_processor/AndroidAopProcessor.java +++ b/android-aop-processor/src/main/java/com/flyjingfish/android_aop_processor/AndroidAopProcessor.java @@ -1,6 +1,7 @@ package com.flyjingfish.android_aop_processor; import com.flyjingfish.android_aop_annotation.anno.AndroidAopCollectMethod; +import com.flyjingfish.android_aop_annotation.anno.AndroidAopReplaceNew; import com.flyjingfish.android_aop_annotation.aop_anno.AopClass; import com.flyjingfish.android_aop_annotation.aop_anno.AopCollectMethod; import com.flyjingfish.android_aop_annotation.aop_anno.AopMatchClassMethod; @@ -26,6 +27,7 @@ import com.squareup.javapoet.TypeSpec; import java.io.IOException; +import java.lang.annotation.Annotation; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -69,6 +71,7 @@ public Set getSupportedAnnotationTypes() { set.add(AndroidAopMatchClassMethod.class.getCanonicalName()); set.add(AndroidAopReplaceClass.class.getCanonicalName()); set.add(AndroidAopReplaceMethod.class.getCanonicalName()); + set.add(AndroidAopReplaceNew.class.getCanonicalName()); set.add(AndroidAopModifyExtendsClass.class.getCanonicalName()); set.add(AndroidAopCollectMethod.class.getCanonicalName()); return set; @@ -103,7 +106,8 @@ public boolean process(Set set, RoundEnvironment roundEnv processPointCut(set, roundEnvironment); processMatch(set, roundEnvironment); - processReplaceMethod(set, roundEnvironment); + processReplaceMethod(set, roundEnvironment,AndroidAopReplaceMethod.class); + processReplaceMethod(set, roundEnvironment,AndroidAopReplaceNew.class); processReplace(set, roundEnvironment); processModifyExtendsClass(set, roundEnvironment); processCollectMethod(set, roundEnvironment); @@ -337,8 +341,8 @@ private void processModifyExtendsClass(Set set, RoundEnvi } } - private void processReplaceMethod(Set set, RoundEnvironment roundEnvironment) { - Set elements = roundEnvironment.getElementsAnnotatedWith(AndroidAopReplaceMethod.class); + private void processReplaceMethod(Set set, RoundEnvironment roundEnvironment,Class var1) { + Set elements = roundEnvironment.getElementsAnnotatedWith(var1); for (Element element : elements) { Name name1 = element.getSimpleName(); boolean isStatic = false; diff --git a/app/src/main/java/com/flyjingfish/androidaop/MainActivity.kt b/app/src/main/java/com/flyjingfish/androidaop/MainActivity.kt index 75269b83..0121e7c6 100644 --- a/app/src/main/java/com/flyjingfish/androidaop/MainActivity.kt +++ b/app/src/main/java/com/flyjingfish/androidaop/MainActivity.kt @@ -137,7 +137,6 @@ class MainActivity: BaseActivity2(), PermissionRejectListener{ TestMatch2(1).test1() TestMatch2().test1() binding.btnTestMuch.setOnClickListener { -// testMatch.test2(1,"2") // // LocaleTransform.getLanguage(1) diff --git a/test-lib/src/main/java/com/flyjingfish/test_lib/ReplaceTestMatch.kt b/test-lib/src/main/java/com/flyjingfish/test_lib/ReplaceTestMatch.kt index 6e009e29..3e06d659 100644 --- a/test-lib/src/main/java/com/flyjingfish/test_lib/ReplaceTestMatch.kt +++ b/test-lib/src/main/java/com/flyjingfish/test_lib/ReplaceTestMatch.kt @@ -3,11 +3,16 @@ package com.flyjingfish.test_lib import android.util.Log import com.flyjingfish.android_aop_annotation.anno.AndroidAopReplaceClass import com.flyjingfish.android_aop_annotation.anno.AndroidAopReplaceMethod +import com.flyjingfish.android_aop_annotation.anno.AndroidAopReplaceNew import com.flyjingfish.android_aop_annotation.enums.MatchType import com.flyjingfish.test_lib.TestMatch @AndroidAopReplaceClass(value = "com.flyjingfish.test_lib.TestMatch",type = MatchType.EXTENDS) object ReplaceTestMatch { + @AndroidAopReplaceNew("()") + @JvmStatic + fun newTestMatch2(testBean: TestMatch3){ + } @AndroidAopReplaceMethod("(int)") @JvmStatic diff --git a/test-lib/src/main/java/com/flyjingfish/test_lib/TestMatch3.java b/test-lib/src/main/java/com/flyjingfish/test_lib/TestMatch3.java new file mode 100644 index 00000000..2647c4d7 --- /dev/null +++ b/test-lib/src/main/java/com/flyjingfish/test_lib/TestMatch3.java @@ -0,0 +1,13 @@ +package com.flyjingfish.test_lib; + + +import com.flyjingfish.test_lib.TestMatch; + +public class TestMatch3 extends TestMatch { + public TestMatch3() { + } + + public TestMatch3(int label) { + super(label); + } +} From 1630ce27f9270a189a962ed2d4aa7de2a9548586 Mon Sep 17 00:00:00 2001 From: tianxiangyu <96164429+FlyJingFish@users.noreply.github.com> Date: Tue, 13 Aug 2024 19:02:10 +0800 Subject: [PATCH 4/5] =?UTF-8?q?1=E3=80=81=E6=96=B0=E5=A2=9E=E6=94=AF?= =?UTF-8?q?=E6=8C=81=E6=9B=BF=E6=8D=A2=E8=B0=83=E7=94=A8=20new?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../android_aop_annotation/anno/AndroidAopReplaceNew.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/android-aop-annotation/src/main/java/com/flyjingfish/android_aop_annotation/anno/AndroidAopReplaceNew.kt b/android-aop-annotation/src/main/java/com/flyjingfish/android_aop_annotation/anno/AndroidAopReplaceNew.kt index bab8c201..c29a8928 100644 --- a/android-aop-annotation/src/main/java/com/flyjingfish/android_aop_annotation/anno/AndroidAopReplaceNew.kt +++ b/android-aop-annotation/src/main/java/com/flyjingfish/android_aop_annotation/anno/AndroidAopReplaceNew.kt @@ -1,8 +1,8 @@ package com.flyjingfish.android_aop_annotation.anno /** - * 定义替换类的构造方法调用的注解,此注解用在替换类的 - * [wiki 文档使用说明](https://github.com/FlyJingFish/AndroidAOP/wiki/@AndroidAopReplaceConstructor) + * 定义替换类的构造方法调用的切面的注解,使用这个注解的方法的类需要使用 [AndroidAopReplaceClass] 注解,否则无用 + * [wiki 文档使用说明](https://github.com/FlyJingFish/AndroidAOP/wiki/@AndroidAopReplaceClass) */ @Target( AnnotationTarget.FUNCTION, From 243cab93ea9bb59e80e27405b614300dd33816e3 Mon Sep 17 00:00:00 2001 From: tianxiangyu <96164429+FlyJingFish@users.noreply.github.com> Date: Tue, 13 Aug 2024 19:04:13 +0800 Subject: [PATCH 5/5] =?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 06b63180..ce9a6dab 100644 --- a/README.md +++ b/README.md @@ -73,7 +73,7 @@ plugins { //必须项 👇 apply 设置为 true 自动为所有module“预”配置debugMode,false则按下边步骤五的方式二 - id "io.github.FlyJingFish.AndroidAop.android-aop" version "2.0.6" apply true + id "io.github.FlyJingFish.AndroidAop.android-aop" version "2.0.7" apply true } ``` @@ -83,7 +83,7 @@ plugins { buildscript { dependencies { //必须项 👇 - classpath 'io.github.FlyJingFish.AndroidAop:android-aop-plugin:2.0.6' + classpath 'io.github.FlyJingFish.AndroidAop:android-aop-plugin:2.0.7' } } // 👇加上这句自动为所有module“预”配置debugMode,不加则按下边步骤五的方式二 @@ -122,7 +122,7 @@ apply plugin: 'android.aop' //最好放在最后一行 //必须项 👇 plugins { ... - id "io.github.FlyJingFish.AndroidAop.android-aop" version "2.0.6"//最好放在最后一行 + id "io.github.FlyJingFish.AndroidAop.android-aop" version "2.0.7"//最好放在最后一行 } ``` @@ -148,17 +148,17 @@ plugins { dependencies { //必须项 👇 - implementation 'io.github.FlyJingFish.AndroidAop:android-aop-core:2.0.6' - implementation 'io.github.FlyJingFish.AndroidAop:android-aop-annotation:2.0.6' + implementation 'io.github.FlyJingFish.AndroidAop:android-aop-core:2.0.7' + implementation 'io.github.FlyJingFish.AndroidAop:android-aop-annotation:2.0.7' //必须项 👇如果您项目内已经有了这项不用加也可以 implementation 'androidx.appcompat:appcompat:1.3.0' // 至少在1.3.0及以上 //非必须项 👇,如果你想自定义切面需要用到,⚠️支持Java和Kotlin代码写的切面 - ksp 'io.github.FlyJingFish.AndroidAop:android-aop-ksp:2.0.6' + ksp 'io.github.FlyJingFish.AndroidAop:android-aop-ksp:2.0.7' //非必须项 👇,如果你想自定义切面需要用到,⚠️只适用于Java代码写的切面 - annotationProcessor 'io.github.FlyJingFish.AndroidAop:android-aop-processor:2.0.6' + annotationProcessor 'io.github.FlyJingFish.AndroidAop:android-aop-processor:2.0.7' //⚠️上边的 android-aop-ksp 和 android-aop-processor 二选一 } ``` diff --git a/README_EN.md b/README_EN.md index 9d18db5d..fc0180b5 100644 --- a/README_EN.md +++ b/README_EN.md @@ -69,7 +69,7 @@ Using the **plugins DSL**: plugins { //Required item 👇 apply is set to true to automatically apply debugMode to all modules, if false, follow step 5 below. - id "io.github.FlyJingFish.AndroidAop.android-aop" version "2.0.6" apply true + id "io.github.FlyJingFish.AndroidAop.android-aop" version "2.0.7" apply true } ``` @@ -80,7 +80,7 @@ plugins { buildscript { dependencies { //Required items 👇 - classpath 'io.github.FlyJingFish.AndroidAop:android-aop-plugin:2.0.6' + classpath 'io.github.FlyJingFish.AndroidAop:android-aop-plugin:2.0.7' } } //👇Add this sentence to automatically apply debugMode to all modules. If not, follow step 5 below. @@ -119,7 +119,7 @@ Add directly to ```build.gradle``` of **app** //Required items 👇 plugins { ... - id "io.github.FlyJingFish.AndroidAop.android-aop" version "2.0.6" + id "io.github.FlyJingFish.AndroidAop.android-aop" version "2.0.7" } ``` @@ -149,16 +149,16 @@ plugins { dependencies { //Required items 👇 - implementation 'io.github.FlyJingFish.AndroidAop:android-aop-core:2.0.6' - implementation 'io.github.FlyJingFish.AndroidAop:android-aop-annotation:2.0.6' + implementation 'io.github.FlyJingFish.AndroidAop:android-aop-core:2.0.7' + implementation 'io.github.FlyJingFish.AndroidAop:android-aop-annotation:2.0.7' //Required item 👇If you already have this item in your project, you don’t need to add it. implementation 'androidx.appcompat:appcompat:1.3.0' // At least in 1.3.0 and above //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:2.0.6' + ksp 'io.github.FlyJingFish.AndroidAop:android-aop-ksp:2.0.7' //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:2.0.6' + annotationProcessor 'io.github.FlyJingFish.AndroidAop:android-aop-processor:2.0.7' //⚠️Choose one of the above android-aop-ksp and android-aop-processor } ``` diff --git a/gradle.properties b/gradle.properties index 5c0bd328..119781d2 100644 --- a/gradle.properties +++ b/gradle.properties @@ -41,7 +41,7 @@ DEVELOPER_ID=FlyJingFish DEVELOPER_NAME=FlyJingFish DEVELOPER_EMAIL=749617782@qq.com -TestVersion = 2.0.6 +TestVersion = 2.0.7 SonatypeTestCode = 1395 TestType = 0 androidAop.debugMode = true diff --git a/version.properties b/version.properties index f046b6a1..2109fd01 100644 --- a/version.properties +++ b/version.properties @@ -1,2 +1,2 @@ -#Thu Aug 08 18:02:35 CST 2024 -PROJ_VERSION=2.0.6 +#Tue Aug 13 19:02:29 CST 2024 +PROJ_VERSION=2.0.7