java动态代理

1. 代理

代购, 中介,换ip,商家等等。

为什么要找中介 ? 
   1. 中介是专业的, 方便
   2. 家长现在不能自己去找学校。 家长没有能力访问学校。 或者美国学校不接收个人来访。

 买东西都是商家卖, 商家是某个商品的代理, 你个人买东西, 肯定不会让你接触到厂家的。

在开发中也会有这样的情况, 你有a类, 本来是调用c类的方法, 完成某个功能。 但是c不让a调用。

a -----不能调用 c的方法。
在a 和 c 直接 创建一个 b 代理,    c让b访问。 
a --访问b---访问c

实际的例子: 登录,注册有验证码, 验证码是手机短信。
中国移动, 联通能发短信。 
中国移动, 联通能有子公司,或者关联公司,他们面向社会提供短信的发送功能
张三项目发送短信----子公司,或者关联公司-----中国移动, 联通

代理的作用

功能增强: 在你原有的功能上,增加了额外的功能。
控制访问: 代理类不让你访问目标,例如商家不让用户访问厂家。

代理的分类

静态代理

  1. 代理类是自己手工实现的,自己创建一个java类,表示代理类。
  2. 同时你所要代理的目标类是确定的。

优点
实现简单,容易理解
缺点
当目标类增加了, 代理类可能也需要成倍的增加。 代理类数量过多;

动态代理

在程序执行过程中,使用jdk的反射机制,创建代理类对象, 并动态的指定要代理目标类。
优点
代理类数量可以很少
当你修改了接口中的方法时,不会影响代理类。
缺点
实现复杂,不容易理解

2. 静态代理

2.1 需求

模拟一个用户购买u盘的行为。
用户(客户端)—商家(代理【类】)—厂家(目标【类】)

2.2 实现步骤

  1. 创建一个接口,定义卖u盘的方法, 表示你的厂家和商家做的事情。
  2. 创建厂家类,实现1步骤的接口
  3. 创建商家,就是代理,也需要实现1步骤中的接口。
  4. 创建客户端类,调用商家的方法买一个u盘。

2.3 具体实现

2.3.1 接口【表示功能的,厂家,商家都要完成的功能】

public interface UsbSell {
    //返回值表示一个u盘的价格。
    float sell(int count);
}

2.3.2 目标类【厂家】

//目标类: 金士顿厂家, 不接受用户的单独购买。
public class UsbKingFactory implements UsbSell {
    @Override
    public float sell(int count) {
        System.out.println("目标类中的方法调用 , UsbKingFactory 中的sell ");
        //一个128G的u盘是 85元。
        return 85;
    }
}

2.3.3 代理类【商家】

public class JD implements UsbSell {
    //声明 商家代理的厂家具体是谁
    private UsbSell factory = new UsbKingFactory();

    @Override
    public float sell(int count) {
        //向厂家发送订单,告诉厂家,我买了u盘,厂家发货
        float price = factory.sell(1);
        //商家 需要加价, 也就是代理要增加价格。
        price += 40;//增强功能,代理类在完成目标类方法调用后,增强了功能。
        System.out.println("京东送您100京东豆!");

        return price;
    }
}

2.3.3 客户端【用户】

public class Customer {
    public static void main(String[] args) {
        JD j = new JD();
        float price = j.sell(1);
        System.out.println(price);
    }
}

2.4 总结

  1. 此时我们只有一家JD卖卖金士顿u盘,当在来一家TaoBao也要卖金士顿u盘时,就要再写一个代理类,这要是有100家企业要买u盘就要写100个代理类,会显得代理类数量过多。并且当目标类【u盘厂家】多起来了之后,代理类都是成倍数上涨的!
  2. 当你的接口中功能增加了, 或者修改了,会影响众多的实现类,厂家类,代理都需要修改。影响比较多。

3. 动态代理

3.1 需求

模拟一个用户购买u盘的行为。
用户(客户端)—商家(代理【类】)—厂家(目标【类】)

3.2 实现步骤

  1. 创建一个接口,定义卖u盘的方法, 表示你的厂家和商家做的事情。
  2. 创建厂家类,实现1步骤的接口
  3. 创建类实现接口InvocationHandler重写invoke()方法, 把原来静态代理中代理类要完成的功能写在这。
  4. 创建客户端类,调用商家的方法买一个u盘

3.3 具体实现

3.3.1 接口【表示功能的,厂家,商家都要完成的功能】

public interface UsbSell {
    float sell(int count);
}

3.3.2 目标类 【厂家】

public class UsbKingFactory implements UsbSell {
    @Override
    public float sell(int count) {
        System.out.println("目标类中的方法调用 , UsbKingFactory 中的sell ");
        return 85;
    }
}

3.3.3 创建类实现接口InvocationHandler

//必须实现InvocationHandler接口,完成代理类要做的功能(1.调用目标方法,2.功能增强)
public class MySellHandler implements InvocationHandler {
    //传入进来的对象
    private Object target;

    //动态代理:目标对象是活动的,不是固定的,需要传入进来。
    //传入是谁,就给谁创建代理。
    public MySellHandler(Object target) {
        this.target = target;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        Object res = null;
        //float price = factory.sell(1);
        res = method.invoke(target, args);//执行目标方法

        //商家 需要加价, 也就是代理要增加价格。
        //price = price + 25; //增强功能,代理类在完成目标类方法调用后,增强了功能。
        if (res != null){
            Float price = (Float) res;
            price += 25;
            res = price;
        }
        //在目标类的方法调用后,你做的其它功能,都是增强的意思。
        System.out.println("淘宝送您优惠券一张!");
        return res;
    }
}

3.3.4 客户端【用户】

public class Customer {
    public static void main(String[] args) {
        //创建代理对象,使用Proxy

        //1. 创建目标对象
        UsbSell factory = new UsbKingFactory();

        //2.创建InvocationHandler对象
        InvocationHandler handler = new MySellHandler(factory);

        //3.创建代理对象
        UsbSell proxy = (UsbSell) Proxy.newProxyInstance(factory.getClass().getClassLoader(), factory.getClass().getInterfaces(), handler);

        //com.sun.proxy.$Proxy0 : 这是jdk动态代理创建的对象类型。
        System.out.println(proxy.getClass().getName());

        //4.通过代理执行方法
        float price = proxy.sell(1);//执行的是MySellHandler类里面的invoke方法
        System.out.println(price);
    }
}

3.4 程序执行流程

在这里插入图片描述
程序执行到proxy.sell(1)语句会调用InvocationHandler实现类的invoke()方法,然后一次执行下来,最终返回值返回给方法调用处proxy.sell(1).

注意:proxy是com.sun.proxy.$Proxy0,所以才会调用InvocationHandler实现类的invoke()方法。

3.5 动态代理

动态代理是一种创建java对象的能力,让你不用创建JD类,就能创建代理类对象。
动态代理使用java反射包中的类和接口实现动态代理的功能。
动态代理使用到的三个类:反射包 java.lang.reflect , 里面有三个类 : InvocationHandler , Method , Proxy

3.5.1 InvocationHandler【接口】

InvocationHandler 接口(调用处理器):就一个方法invoke()
invoke():表示代理对象要执行的功能代码。你的代理类要完成的功能就写在invoke()方法中。

3.5.2 Method

3.5.3 Proxy.newProxyInstance() 方法【静态方法】

创建代理对象, 等同于静态代理中的TaoBao taoBao = new TaoBao();

public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)

ClassLoader loader 类加载器,负责向内存中加载对象的。 使用反射获取对象的ClassLoader.【类a , a.getCalss().getClassLoader(), 目标对象的类加载器】
Class<?>[] interfaces: 接口, 目标对象实现的接口,也是反射获取的。【类a , a.getClass().getInterfaces().】
InvocationHandler h : 我们自己写的,代理类要完成的功能。
返回值:就是代理对象。

来源:https://blog.csdn.net/qq_44715943/article/details/120785432

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值