java静态代理和动态代理

代理是什么呢?
代理可以理解为代购,虽然最终结果是你买了商品,但是是代购替你买回来的。

静态代理

// 接口
public interface Shopping {
    Object[] doShopping(double money);
}
// 实现类:你买东西
public class ShoppingImpl implements Shopping {
    @Override
    public Object[] doShopping(double money) {
        System.out.println(String.format("花%s块钱买东西。", money));
        Object o[] = {"衣服", "手机", "MacBook Pro"};
        return o;
    }
}
// 静态代理类:代理替你买东西
public class ProxyShopping implements Shopping {
    public static void main(String args[]) {
        // 其实本质还是你买
        Shopping shopping = new ShoppingImpl();
        System.out.println(Arrays.toString(new ProxyShopping(shopping).doShopping(6000)));
    }

    private Shopping shopping;

    public ProxyShopping(Shopping shopping) {
        this.shopping = shopping;
    }

    @Override
    public Object[] doShopping(double money) {
        System.out.println("使用静态代理来购物...");
        Object[] o = shopping.doShopping(money);
        if (o != null && o.length > 1) {
            o[0] = "被掉包的东西!!!";
        }
        return o;
    }
}

动态代理

传统的静态代理需要为每一个被代理的类写一个代理,比较麻烦。所以有了动态代理,动态代理主要是用InvocationHandlerProxy类。

public class ShoppingHandler implements InvocationHandler {
    public static void main(String args[]) {
        Shopping shopping = new ShoppingImpl();
        // 得到代理对象
        shopping = (Shopping) Proxy.newProxyInstance
            (Shopping.class.getClassLoader(), shopping.getClass().getInterfaces(), new ShoppingHandler(shopping));
        System.out.println(Arrays.toString(shopping.doShopping(600)));
}
    // 被代理的对象
    private Object obj;

    public ShoppingHandler(Object obj) {
        this.obj = obj;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        if (method.getName().equals("doShopping")) {
            System.out.println("动态代理:执行操作-可以修改入参");
            Object[] ob = (Object[]) method.invoke(obj, args[0]);
            System.out.println("动态代理:执行操作-可以修改返回值");
            return ob;
        }
        return null;
    }
}

区别

他们两个都是代理,那么在使用时有什么区别呢?
静态代理和动态代理都是要创建代理对象,以达到某些目的。
区别就是:

  1. 动态代理只试用于被代理对象是接口的情况,为什么呢?
    因为动态代理在创建代理对象的时候会检测对象是否实现了接口,如果没有则报空指针错误。
  2. 静态代理需要为每个代理对象编写代理类,而动态代理则不用。动态代理更加灵活。

参考文章:http://weishu.me/2016/01/28/understand-plugin-framework-proxy-hook/

动态代理生成的class文件

其中包括:你的接口中的方法、Object类中的 toString()、equals()、hashCode()
如何生成?
在你执行动态代理代码的地方加上:

try {
   Field field = null;
    field = System.class.getDeclaredField("props");

    field.setAccessible(true);
    Properties props = null;
    props = (Properties) field.get(null);
    props.put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");
} catch (NoSuchFieldException e) {
    e.printStackTrace();
} catch (IllegalAccessException e) {
    e.printStackTrace();
}

会在 com/sun/proxy 文件夹下生成 class 文件

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

package com.sun.proxy;

import com.weishu.upf.dynamic_proxy_hook.app2.Shopping;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException;

public final class $Proxy0 extends Proxy implements Shopping {
    private static Method m1;
    private static Method m3;
    private static Method m2;
    private static Method m0;

    public $Proxy0(InvocationHandler var1) throws  {
        super(var1);
    }

    public final boolean equals(Object var1) throws  {
        try {
            return ((Boolean)super.h.invoke(this, m1, new Object[]{var1})).booleanValue();
        } catch (RuntimeException | Error var3) {
            throw var3;
        } catch (Throwable var4) {
            throw new UndeclaredThrowableException(var4);
        }
    }

    public final Object[] doShopping(long var1) throws  {
        try {
            return (Object[])super.h.invoke(this, m3, new Object[]{Long.valueOf(var1)});
        } catch (RuntimeException | Error var4) {
            throw var4;
        } catch (Throwable var5) {
            throw new UndeclaredThrowableException(var5);
        }
    }

    public final String toString() throws  {
        try {
            return (String)super.h.invoke(this, m2, (Object[])null);
        } catch (RuntimeException | Error var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }

    public final int hashCode() throws  {
        try {
            return ((Integer)super.h.invoke(this, m0, (Object[])null)).intValue();
        } catch (RuntimeException | Error var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }

    static {
        try {
            m1 = Class.forName("java.lang.Object").getMethod("equals", new Class[]{Class.forName("java.lang.Object")});
            m3 = Class.forName("com.weishu.upf.dynamic_proxy_hook.app2.Shopping").getMethod("doShopping", new Class[]{Long.TYPE});
            m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]);
            m0 = Class.forName("java.lang.Object").getMethod("hashCode", new Class[0]);
        } catch (NoSuchMethodException var2) {
            throw new NoSuchMethodError(var2.getMessage());
        } catch (ClassNotFoundException var3) {
            throw new NoClassDefFoundError(var3.getMessage());
        }
    }
}

仔细看看上面的代码!

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

outer199

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值