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();
    }
}

运行结果:

image.png