源代码:https://gitee.com/kotlin_zone/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
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")
}
}