代理模式

文章目录[x]
  1. 1:静态代理
  2. 2:动态代理
  3. 2.1:JDK动态代理
  4. 2.2:GCLib动态代理
  5. 2.3:CGLib for Android动态代理

代理模式是基本的设计模式之一,它是为了提供额外的或不同的操作而插入的用以代替实际的“对象”的对象,该代理对象通常继承自实际对象或将实际对象作为自己的成员变量,因此能够在提供额外操作的同时与“实际对象”通信调用其原有的功能。

静态代理

静态代理指的是:由程序员创建或特定工具自动生成源代码,再对其编译。在程序运行前,代理类的.class文件就已经存在了。

/**
* @author Melrose
* @since 1.0.0
*/

 

interface IProxy{
fun handle()
}

 

class IProxyImpl:IProxy{
override fun handle() {
println("handle")
}
}

 

class Proxy(private val impl:IProxy):IProxy{
override fun handle() {
println("start")
impl.handle()
println("end")
}
}

 

fun main(args: Array<String>) {
val impl = IProxyImpl()
val proxy = Proxy(impl)
proxy.handle()
}

从上例可以看到在静态代理中,一个委托类对应一个代理类,代理类在编译期间就已经确定。另外,如果没有使用接口,代理类也可以通过继承委托类实现静态代理。

动态代理

动态代理:代理类是在程序运行时运用反射机制动态创建而成。主要有 JDK 动态代理和 CGLib 动态代理CGLib for Android动态代理

JDK 实现动态代理需要实现类通过接口定义方法,对于没有接口的类,这就需要 CGLib了。CGLib 采用了非常底层的字节码技术,其原理是通过字节码技术为一个类创建子类(继承的方式),并在子类中采用方法拦截的技术拦截所有父类方法的调用,顺势织入横切逻辑。

JDK动态代理

import java.lang.reflect.InvocationHandler
import java.lang.reflect.Method
import java.lang.reflect.Proxy
import java.util.*

/**
* @author Melrose
* @since 1.0.0
*/

interface IProxy{
fun handle()
}

 

class ProxyImpl : IProxy{
override fun handle() {
println("handle")
}
}

class ProxyHandler(private val impl: IProxy):InvocationHandler{

fun getProxy() = Proxy.newProxyInstance(javaClass.classLoader, arrayOf(IProxy::class.java),this) as IProxy

override fun invoke(proxy: Any?, method: Method?, args: Array<out Any>?): Any? {
println("start")
return method?.invoke(impl)
}

}

fun main(args: Array<String>) {
ProxyHandler(ProxyImpl()).getProxy().handle()
}

JDK 动态代理类的字节码在程序运行时由 Java 反射机制动态生成,无需手工编写它的源代码。动态代理类不仅简化了编程工作,而且提高了软件系统的可扩展性,因为 Java 反射机制可以生成任意类型的动态代理类。java.lang.reflect 包中的Proxy类和InvocationHandler接口提供了生成动态代理类的能力。

GCLib动态代理

JDK 中提供的生成动态代理类的机制的特点是:某个类必须有实现的接口,如果某个类没有实现接口,那么这个类就不能通过 JDK 产生动态代理了。这就需要使用CGLibCGLIBCode Generation Library)是一个强大的、高性能、高质量的代码生成类库,它可以在运行期扩展Java类与实现Java接口。

import net.sf.cglib.proxy.Enhancer
import net.sf.cglib.proxy.MethodInterceptor
import net.sf.cglib.proxy.MethodProxy
import java.lang.reflect.Method

/**
* @author Melrose
* @since 1.0.0
*/

 

open class Target{
fun print(){
println("target")
}
}

 

class CGLibProxy(private val obj:Any):MethodInterceptor{
fun getProxy() = Enhancer().apply {
setSuperclass(obj.javaClass)
setCallback(this@CGLibProxy)
}.create()

override fun intercept(p0: Any?, p1: Method?, p2: Array<out Any>?, p3: MethodProxy?): Any? {
println("start")
p3?.invoke(p0,p2)
println("end")
return null
}

}

 

fun main(args: Array<String>) {
CGLibProxy(Target()).getProxy()?.let {
(it as Target).print()
}
}

注意由于 CGLib 动态代理采用的是继承委托类的方式,因此不能代理 final 修饰的类。如果将上例中的类Target 去掉open修饰符就会抛出IllegalArgumentException异常;

CGLib for Android动态代理

由于CGLib动态代理生成的是.class,这在安卓上行不通。这样就可以使用CGLib for AndroidCGLib for AndroidAndroidDex代码生成库)是用于动态生成子类的高级API,其实现基于DexMaker。 该库可以用于AOP,方法拦截,Android上的数据访问授权身份验证。

open class Target{
fun print(){
println("target")
}
}

class CGLibAndroidProxy(private val obj:Any,private val cxt:Context): MethodInterceptor {

 

fun getProxy() = Enhancer(cxt).apply {
setSuperclass(obj.javaClass)
setInterceptor(this@CGLibAndroidProxy)
}.create()

override fun intercept(p0: Any?, p1: Array<out Any>?, p2: MethodProxy?): Any? {
println("start")
val result = p2?.invokeSuper(p0,p1)

return result
}

 

}

fun main(args: Array<String>) {
CGLibAndroidProxy(Target(),context).getProxy()?.let {
(it as Target).print()
}
}

 

点赞

发表评论

昵称和uid可以选填一个,填邮箱必填(留言回复后将会发邮件给你)
tips:输入uid可以快速获得你的昵称和头像

Title - Artist
0:00