@cxm-2016
2016-12-29T13:56:33.000000Z
字数 1924
阅读 2140
Java
版本:1
作者:陈小默
声明:禁止商业,禁止转载
Java中实现一个动态代理通常有两种方式:
jdk动态代理是由Java内部的反射机制来实现的,cglib动态代理底层则是借助asm来实现的。总的来说,反射机制在生成类的过程中比较高效,而asm在生成类之后的相关执行过程中比较高效(可以通过将asm生成的类进行缓存,这样解决asm生成类过程低效问题)。还有一点必须注意:jdk动态代理的应用前提,必须是目标类基于统一的接口。如果没有上述前提,jdk动态代理不能应用。
interface User {
fun getName(): String
fun getAge(): Int
}
class UserImpl(private val name: String,
private val age: Int) : User {
override fun getName(): String {
return name
}
override fun getAge(): Int {
return age
}
}
class UserProxy(private val user: User) : InvocationHandler {
fun proxy(): User {
return Proxy.newProxyInstance(user.javaClass.classLoader,
user.javaClass.interfaces,
this) as User
}
override fun invoke(proxy: Any?, method: Method, args: Array<out Any>?): Any {
return when (method.name) {
"getName" -> {
val name = method.invoke(user)
"$name Chou"
}
"getAge" -> {
val age = method.invoke(user) as Int
age + 3
}
else -> {
method.invoke(user, args)
}
}
}
}
从实现中可以看出Java动态代理的实现方式是基于反射的实现,将反射出的方法对象和参数取出,然后交给InvocationHandler
的invoke
方法自行实现。这里我们将对象更改为自己的User实例,修改调用结果并且返回。
fun main(args: Array<String>) {
val user = UserProxy(UserImpl("Jack", 22)).proxy()
println(user.getName())
println(user.getAge())
}
CGLIB是一个强大的高性能的代码生成包。
CGLIB在实现动态代理的过程中要求被代理的类能够被继承,也就是说不能够是被final
修饰的。
class UserProxy() : MethodInterceptor {
fun <T> proxy(clazz: Class<T>, argTypes: Array<out Class<out Any>>? = null, args: Array<out Any>? = null): T {
val enhancer = Enhancer()
enhancer.setSuperclass(clazz)
enhancer.setCallback(this)
return enhancer.create(argTypes, args) as T
}
override fun intercept(proxy: Any, method: Method, args: Array<out Any>?, methodProxy: MethodProxy): Any {
return when (method.name) {
"getName" -> {
val name = methodProxy.invokeSuper(proxy, args)
"$name Chou"
}
"getAge" -> {
val age = methodProxy.invokeSuper(proxy, args) as Int
age + 10
}
else -> {
methodProxy.invokeSuper(proxy, args)
}
}
}
}