Kotlin中如何无需重写全部run方法修改第三方类私有print方法
问题解答
你当前复制粘贴整个run方法的实现存在明显的维护缺陷:一旦后续第三方库升级修改了run方法的逻辑,你必须同步更新你复制的代码,否则会出现逻辑不一致的问题,长期维护成本极高。以下是几种更优的实现方案:
方案1:字节码增强(无侵入,无需修改继承逻辑)
你可以使用Byte Buddy、ASM等JVM字节码增强工具,在类加载阶段直接修改第三方类的print方法实现,完全不需要改动你原有业务代码,也不需要复制run方法的逻辑,后续第三方库升级也不用同步修改你的代码。
示例代码(基于Byte Buddy):
ByteBuddy() .redefine(A_CLASS_FROM_3RD_PARTY_LIBRARY_THAT_I_CANNOT_MODIFY::class.java) .method(named("print")) .intercept { // 替换为你自己的print逻辑 println("B") null } .make() .load( A_CLASS_FROM_3RD_PARTY_LIBRARY_THAT_I_CANNOT_MODIFY::class.java.classLoader, ClassLoadingStrategy.Default.INJECTION )
方案2:AOP切面(适合已接入AOP框架的项目)
如果你的项目使用了Spring等支持AOP的框架,可以直接给第三方类的print方法添加环绕通知,跳过原有逻辑执行你自己的实现:
@Around("execution(* 第三方类包名.A_CLASS_FROM_3RD_PARTY_LIBRARY_THAT_I_CANNOT_MODIFY.print(..))") fun replacePrintLogic(joinPoint: ProceedingJoinPoint) { // 不执行原有print方法,直接走自定义逻辑 println("B") }
方案3:输出流拦截(兼容性最高,无黑科技依赖)
如果你不想用字节码修改、反射这类有环境限制的实现,可以通过临时重定向系统输出流的方式替换输出内容:
class B : A_CLASS_FROM_3RD_PARTY_LIBRARY_THAT_I_CANNOT_MODIFY() { override fun run() { val originOut = System.out // 临时替换输出流,捕获"A"输出替换为"B" System.setOut(PrintStream(object : FilterOutputStream(originOut) { private val lineBuffer = StringBuilder() override fun write(b: Int) { lineBuffer.append(b.toChar()) if (lineBuffer.endsWith(System.lineSeparator())) { val content = lineBuffer.toString().trim() lineBuffer.clear() if (content == "A") { originOut.println("B") } else { originOut.println(content) } } } })) try { // 直接调用父类的run方法,不用复制代码 super.run() } finally { // 恢复原有输出流 System.setOut(originOut) } } }
这种方案完全不需要依赖额外框架,也不需要修改字节码,兼容性最高,缺点是仅适用于print方法是做控制台输出的场景,如果print方法有其他逻辑就不适用。
内容的提问来源于stack exchange,提问作者iForests
相关产品推荐
相关产品推荐

