0
点赞
收藏
分享

微信扫一扫

为什么 Kotlin 使用 cglib 的 Enhancer 动态代理不生效?

源代码:​​https://gitee.com/kotlin_zone/proxy​​

为什么 Kotlin 使用 cglib 的 Enhancer 动态代理不生效?_proxy

Kotlin 代码 NG:

package com.light.sword

/**
* @author: Jack
* 2020-09-11 10:59
*/
open class Hello {
fun hello() {
println("Hello")
}
}


package com.light.sword

import net.sf.cglib.proxy.MethodInterceptor
import net.sf.cglib.proxy.MethodProxy
import java.lang.reflect.Method
import kotlin.jvm.Throws


/**
* @author: Jack
* 2020-09-11 10:59
*/

class HelloProxy : MethodInterceptor {

@Throws(Throwable::class)
override fun intercept(obj: Any?, p1: Method?, args: Array<out Any>?, proxy: MethodProxy?): Any {
println("Before")
proxy?.invokeSuper(obj, args)
println("After")
return Any()
}

}

package com.light.sword

import net.sf.cglib.proxy.Enhancer


fun main() {
val enhancer = Enhancer()
enhancer.setSuperclass(Hello::class.java)
// 回调方法的参数为代理类对象
enhancer.setCallback(HelloProxy())
// 增强过的目标类
val enhancedHello = enhancer.create()
enhancedHello as Hello
enhancedHello.hello()
}

output:

Hello

为什么 Kotlin 使用 cglib 的 Enhancer 动态代理不生效?_回调方法_02

Debug的时候报错:

Method threw 'java.lang.ClassCastException' exception. Cannot evaluate com.light.sword.Hello$$EnhancerByCGLIB$$6db4e38.toString()

Java 代码是OK的:

package com.light.sword;

/**
* @author: Jack
* 2020/9/11 15:29
*/
public class WorldJ {
public void world(){
System.out.println("World!");
}
}


package com.light.sword;

import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;

/**
* @author: Jack
* 2020/9/11 15:29
*/
public class WorldJProxy implements MethodInterceptor {

public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
System.out.println("Before");
methodProxy.invokeSuper(o, args);
System.out.println("After");
return null;
}

}


package com.light.sword;

import net.sf.cglib.proxy.Enhancer;

/**
* @author: Jack
* 2020/9/11 15:34
*/
public class WorldJTest {
public static void main(String[] args) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(WorldJ.class);
enhancer.setCallback(new WorldJProxy());
WorldJ enhanceWorldJ = (WorldJ) enhancer.create();
enhanceWorldJ.world();
}
}

output:

Before
World!
After

原因分析

因为Kotlin的class 默认是final的, fun 默认也是final的,cglib对final的方法,是不走Proxy callback的。

解决方案

把需要代理的 fun 设置为 open。

package com.light.sword

/**
* @author: Jack
* 2020-09-11 10:59
*/
open class Hello {
open fun hello() {
println("Hello")
}
}


举报

相关推荐

0 条评论