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

源代码: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")
    }
}

猜你喜欢

转载自blog.csdn.net/universsky2015/article/details/108544320