实现动态代理

202 阅读2分钟

我们这里使用用户租房的例子。

1、先定义一个接口,将我们委托类的要做的行为,给他抽象出来,在接口中定义一个抽象方法。

public interface ZuFang(){
    //定义一个租房的方法
    public void zuFang();
}

2、定义一个委托类(房东),实现租房接口

public class WeiTuo implements ZuFang{
    //房东要租房子
    public void zuFang(){
        System.out.pringln("房东要出租房子!");
    }
}

3、定义一个中介类

/*中介类需要干两件事情
    1、将房东对象作为私有属性。
    2、实现invoke方法。
*/
public class DynamicProxy implements InvocationHandler{
    //委托类作为内置属性
    Object obj;
    
    public DynamicProxy(Object obj){
        this.obj=obj;
    }

    public Object invoke(Object proxy,Method method,Object[] args){
      /*
        Class<WeiTuo> c1 = WeiTuo.class;
 		Method zuFang = c1.getDeclaredMethod("要调用的该类中存在的方法名");
       String result = zuFang.invoke(c1.newInstance(),null);
        */
       //这里通过method.invoke(反射),实际是调用的obj(也就是房东对象)的方法。
       //参考上面的注释了的代码
       
        //执行方法返回的返回值
        String result= method.invoke(obj,args);
        System.out.pringln("中介带客户看房!");   
        System.out.pringln("中间收取看房费用");
            return result;
    }
}

到目前为止,中介类就是代理类,委托类还是委托类。

4、调用Proxy类的newProxyInstance方法,生成代理类对象。

public class MyTest(){
    public static void main(String[] args){
        //先创建中介类对象,并将委托类赋值给中介类对象的属性
        DynamicProxy dp=new DynamicProxy(new WeiTuo());
        
        //必须要加这句话,不然执行不了
            System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles","true");
    
        //调用Proxy.newProxyInstance方法
          /**
         * 参数1、接口类的类加载器
         * 参数2、接口名字
         * 参数3、中介类的实例对象
         */
        ZuFang zfProxy=(ZuFang)Proxy.newProxyInstance(
                                ZuFang.class.getClassLoader(),
                                new Class[]{ZuFang.class,
                                dp
        });
            //代理类调用租房方法
            zfProxy.zuFang();        
    }
}

展示测试结果

到这里,刚才的中介类就变成了委托类,新建的代理类,就是代理类。

两个静态代理的关系

动态代理的好处:

解决了静态代理的缺点,一个代理类只能代理一个委托类(动态代理不管有多少个委托类,一个代理类就能解决)。动态代理是无入侵式的代码扩展。不修改源码的情况下,增强一些功能,

动态代理的原理:我们通过Proxy.newProxyInstance()方法生成实例代理类的对象,实例代理对象调用代理方法,实际上变成了中介类调用invoke方法,中介类通过构造方法的时候赋值了内置属性,房东类,变成了中介调用我们的委托类。我们在委托类中还可以添加自己的逻辑功能代码(功能增强)。