- 1:静态代理
- 2:动态代理
- 2.1:JDK动态代理
- 2.2:GCLib动态代理
- 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 产生动态代理了。这就需要使用CGLib。CGLIB(Code 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 Android,CGLib for Android(Android的Dex代码生成库)是用于动态生成子类的高级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()
}
}