什么是动态代理?实际开发中如何使用?

什么是动态代理?

  • 使用JDK的反射机制,创建对象的能力,创建的是代理类的对象,不用程序员自己创建类文件
  • 动态:在程序执行时,调用JDK提供的方法才能创建代理类的对象
  • 有两种动态代理的方式:
    • 1) jdk动态代理,通过反射包中的类和接口实现动态代理
    • 2) cglib动态代理,cglib是第三方的工具库,通过继承目标类,创建子类实现动态代理

什么是代理类对象?

假如 :a是用户,c是厂家,一般来说,a如果想购物,是不能直接去厂家买东西的,所以出现了一个代理–淘宝b

a不能直接访问c,但是可以通过b访问c,即:a->b->c

代理对象可以实现目标对象的方法,即b实现了c的方法,且a调用b的方法

且在代理对象实现目标对象的方法时候,可以拥有自己的方法,达到增强功能的作用

比如:b淘宝实现c厂家卖东西的功能------c厂家有卖东西的方法,b淘宝也有卖东西的方法

但是b淘宝除了卖东西之外,还可以写闲置的方法


为什么不用静态代理?

静态代理对象是我们手动创建的,且当代理对象实现了目标对象的方法之后,如果接口需要对方法进行改动,那么所有的实现类都需要进行改动,过于麻烦,所以采用动态代理


知道动态代理能做什么?

可以在不改变原来目标方法功能的前提下,可以在代理中增强自己的功能代码

程序开发中:

  • 项目中,有人写好了一个功能,大家可以使用。
  • Gongneng .class
  • Gongneng gn =new Gongneng ()
  • gn.print();
  • 你发现这个功能,现在还缺点东西,不能完全满足我自己项目的需要,我需要在gn.print()执行后,需要添加自己的代码。可以用代理实现gn.print(),调用后,增加自己的代码,而不用去改原来的Gonneng文件

jdk动态代理

  1. InvocationHandler 接口(调用处理器),里面只有一个方法invoke()这个方法跟反射调用方法没关系

    这个接口表示:你的代理对象需要干什么?需要实现的功能

    public interface InvocationHandler {
        //var1是jdk创建的代理对象
        //var2是目标类中的方法,jdk提供method对象的
        //var3是目标类中的方法参数,jdk提供的
        Object invoke(Object var1, Method var2, Object[] var3) throws Throwable;
    }
    
  2. Method类:表示方法,目标类中的方法

    作用:通过Method可以执行某个目标类的方法:Method.invoke()–>通过反射机制调用方法,执行目标方法

  3. Proxy类:核心的对象,创建代理对象,之前创建对象都是new类的构造方法(),限制是使用Proxy类的方法,代替new的使用

    方法:静态方法 newProxyInstance()

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

    参数:

    • ClassLoader loader :类加载器,负责向内存中加载对象,使用反射获取对象的类 a,a.getClass.getClassLoder()
    • Class<?>[] interfaces :接口,目标对象实现的接口,通过反射获取
    • InvocationHandler h :我们自己写的代理类要完成的功能

    返回值就是代理对象


实现动态代理的步骤

  1. 创建接口,定义目标类要完成的功能
  2. 创建目标类实现接口
  3. 创建InvocationHandler接口的实现类,在invoke方法中完成代理类的功能
    • 调用目标方法
    • 增强功能
  4. 使用Proxy类的静态方法,创建代理对象,并把返回值转为接口类型
//接口
public interface UsbSell {
    float sell(int count);
}
//目标类(厂家)
public class UsbKingFactory implements UsbSell{
    @Override
    public float sell(int count) {
        System.out.println("目标类执行sell目标方法");
        return 80f;
    }
}

//必须实现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[] argss) throws Throwable {
         Object res=null;
        //等于:
//        UsbSell usbFactory = new UsbKingFactory();
//        float price = usbFactory.sell(100);
        res = method.invoke(target, args);//执行目标方法

        //商家需要加价,也就是代理要增加价格
        //price = price +2
        if (res!=null) {
            Float price = (Float) res;
            price = price + 2;
            res = price;
        }
        return res;
    }
}

//
public class MainShop {
    public static void main(String[] args) {
        //1.创建目标对象
        UsbSell factory = new UsbKingFactory();
        //2.创建InvocationHandler对象
        InvocationHandler hander = new MySellHandler(factory);
        //3.创建代理对象
        UsbSell proxy = (UsbSell)Proxy.newProxyInstance(
                factory.getClass().getClassLoader(),factory.getClass().getInterfaces(),hander);
        //4.通过代理执行方法
        float price = proxy.sell(20);
        System.out.println(price);
    }
}

在这里插入图片描述


具体案例实现

public interface HelloService {
    int print();
}
public class Goneng implements HelloService{
    @Override
    public int print() {
        System.out.println("其他人写好的功能");
        return 2;
    }
}
//以上部分是其他人写好的功能方法,可以让别人调用的
//实现InvocationHandler接口,完成代理类要做的功能
//此处功能是实现目标类(功能方法),和增强功能(自己的代码自己的需求)
public class MyInvocationHandler implements InvocationHandler {
    private Object target;
    public MyInvocationHandler(Object target) {
        this.target = target;
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //调用目标方法得到的是2
        Integer num = 0;
        Object res = method.invoke(target, args);//2
        if (res !=null){
            num = (Integer) res;
            num = num*2;
        }
        return num;
    }
}
public class MyApp {
    public static void main(String[] args) {
        Goneng goneng = new Goneng();
        MyInvocationHandler handler = new MyInvocationHandler(goneng);
        HelloService proxy = (HelloService) Proxy.newProxyInstance(goneng.getClass().getClassLoader(), goneng.getClass().getInterfaces(), handler);
        int num = proxy.print();
        System.out.println("代理后:"+num);//4
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值