动态代理转载
原创让我们来比较一下Java的 class
和 interface
的区别:
- 可以实例化
class
(非abstract
); - 无法实例化
interface
。
所有 interface
类型的变量始终向上转换并指向一个实例:
CharSequence cs = new StringBuilder();
有没有可能不编写实现类而直接在运行时创建实现类? interface
那么这个实例呢?
这是可能的,因为Java标准库提供了一个动态代理(Dynamic Proxy)机制:您可以动态创建 interface
的实例。
什么是运行时动态创建?这听起来很复杂。所谓的动态动因对应于静态。让我们来看看静态代码是如何编写的:
定义接口:
public interface Hello {
void morning(String name);
}
编写实现类:
public class HelloWorld implements Hello {
public void morning(String name) {
System.out.println("Good morning, " + name);
}
}
创建实例,转换为接口,调用:
Hello hello = new HelloWorld();
hello.morning("Bob");
这是我们通常编写代码的方式。
另一种方式是动态代码,我们仍然首先定义接口。 Hello
,但我们不编写实现类,而是直接通过。JDK提供了一个 Proxy.newProxyInstance()
创建了一个 Hello
接口对象。这种不实现类但在运行时动态创建接口对象的方式称为动态代码。JDK提供的动态创建接口对象的方法称为动态代理。
最简单的动态代理实现之一如下:
import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy;
Run
动态创建一个 interface
示例如下:
- 定义一个
InvocationHandler
实例,负责实现接口的方法调用; - 通过
Proxy.newProxyInstance()
创建interface
实例,它需要3个参数:- 使用的
ClassLoader
通常是接口类。ClassLoader
; - 要实现的接口数组需要至少传入一个接口;
- 用于处理接口方法调用。
InvocationHandler
实例。
- 使用的
- 将返回的
Object
强制转换为接口。
动态代理实际上是JDK在运行时动态创建class字节码和加载进程,它没有任何黑魔法,上面的动态代理重写静态实现类大概就这么长:
public class HelloDynamicProxy implements Hello {
InvocationHandler handler;
public HelloDynamicProxy(InvocationHandler handler) {
this.handler = handler;
}
public void morning(String name) {
handler.invoke(
this,
Hello.class.getMethod("morning"),
new Object[] { name });
}
}
其实就是JDK帮我们自动写一个上面的类(不需要源代码,可以直接生成字节码),没有黑魔法可以直接实例化接口。
小结
Java标准库提供了动态代理功能,允许动态创建一个接口的实例;
制作了动态代理 Proxy
创建一个代理对象,然后“代理”接口方法。 InvocationHandler
完成的。
地址: https://www.liaoxuefeng.com/wiki/1252599548343744/1264804593397984
版权声明
所有资源都来源于爬虫采集,如有侵权请联系我们,我们将立即删除