Java动态代理、静态代理 初步
代理
主要记录两种代理(静态代理、动态代理) 的初步理解,同时两种代理记录在一块,以便于对比理解记忆。
所谓代理,类似于一个中间人的角色,如明星的经纪人(代理类),广告需求方需要广告,经纪人代理明星的接广告事宜,但是真正拍广告的还是明星,一个经纪人固定了一个明星(被代理类),那么此时类似于我们的静态代理(当然,也能够使用动态代理),而当一个经纪人手下有很多明星时,当他接到一个一个广告时,仅仅通过一个代理经纪人,就可以完成很多明星的代理,此时广告究竟哪个明星拍,是不确定的,可以明星1也可以是明星2,此为动态代理,可知,静态代理的被代理类是固定的,因此我们可以直接编码静态代理,而动态代理的被代理类是不确定的,那么动态代理的代理类是在运行时自动生成的。
对于广告需求方来说,和他交易的是经纪人,经纪人可以交付广告,真正交付的明星,说明明星也是交付广告,可知经纪人(代理)和明星(被代理)实现同一个接口
(此部分类比为后加上去,与下文代码不那么贴合)
准备工作:
为了便于后续的代码示例,先准备一个接口,两个接口的实现类(被代理类),如下:
//接口
interface Productor{
void work();
void sell();
}
//被代理类1 Dell
class Dell implements Productor{
public void work() {
System.out.println("dell生产了一批商品");
}
public void sell() {
System.out.println("dell将商品出售了");
}
}
//被代理类2 AUSA
class AUSA implements Productor{
public void work() {
System.out.println("AUSA生产了一批商品");
}
public void sell() {
System.out.println("AUSA将商品出售了");
}
}
静态代理
静态代理即写死了的代理,被代理者是明确的。
示例如下,通过调用代理的相应方法进而运行被代理类的方法完成任务。
//静态代理类
class StaticProxy implements Productor{
Productor productor;
public void setProductor(Productor productor) {
this.productor = productor;
}
public void work() {
productor.work();
}
public void sell() {
productor.sell();
}
}
动态代理
动态代理,即不确定被代理类,只有在运行时才知道究竟代理的是哪个类,对比上述的静态代理类,我们无法编写出一个固定针对某一个被代理类的代理类,Java提供了在运行中自动生成代理类的方案。
示例及注释如下所示
//动态代理类
class ProxyFactory{
//自定义方法,传入参数为被代理对象
public static Object getProxyInstance(Object obj){
//1.1 在下面的Proxy.newProxyInstance方法中,需要一个InvocationHandler接口
//的实现类对象作为参数传入,详细解释转到下面代码注释 1.2 处
MyInvocationHandler myInvocationHandler=new MyInvocationHandler();
myInvocationHandler.setObj(obj);
//1.3 使用Proxy.newProxyInstance方法生成代理对象,
//返回的对象o即为生成的代理对象,该方法三个参数,被代理对象的加载器、
//被代理对象的接口、InvocationHandler接口的实现类
//当我们调用代理对象o实现的接口方法后,实际上运行的是参数3即InvocationHandler实现类的invoke方法(1.4),
Object o = Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), myInvocationHandler);
return o;
}
}
class MyInvocationHandler implements InvocationHandler{
private Object obj;//此对象是需要被代理对象
public void setObj(Object obj) {//传入被代理对象
this.obj = obj;
}
//1.2 接口方法,该方法是主要的动态代理方法,
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//1.4 obj是被代理对象,args是方法参数,当1.3发生调用时,比如调用的是work()方法,此时method表示的是work方法,obj表示是被代理对象的work方法,args表示1.3传递过来的work方法参数。
Object invoke = method.invoke(obj, args);
return invoke;
}
}
运行测试
public class ProxyTest {
public static void main(String[] args) {
Dell dell = new Dell();//创建一个被代理对象
//通过动态代理获得一个代理对象,由于代理对象和被代理对象均实现了Productor接口,所以转换为Productor对象,通过代理对象调用方法
Productor proxyInstance = (Productor) ProxyFactory.getProxyInstance(dell);
proxyInstance.work();
proxyInstance.sell();
//使用AUSA对比,可知一个动态代理可代理多个实现了Productor接口的对象
AUSA ausa = new AUSA();
Productor proxyInstance1 = (Productor) ProxyFactory.getProxyInstance(ausa);
proxyInstance1.work();
proxyInstance1.sell();
}
}
运行结果: