动态代理-JDK动态代理

1、 什么是代理模式?

当一个对象不能直接使用,可以在客户端和目标对象之间创建一个中介,这个中介就是代理

作用:

1.控制访问:在代理模式中,控制是否可以调用目标对象的方法

2.功能增强:可以在完成目标对象的调用时,附加一些额外的功能,这些额外的功能叫做功能增强

代理的实现方式:

1.静态代理:代理类是手动实现的一个java文件,同时代理的目标对象是固定的

优点:容易理解,使用方便

缺点:在目标类比较多的时候,会产生大量的代理类;当接口改变时,所影响的目标类和代理类比较多

2.动态代理:使用反射机制,在程序的执行中,创建代理类对象

优点:不用创建代理类文件,代理的目标类是活动的,可设置的,可以给不同的目标随时创建代理

动态代理的实现:

1.jdk动态代理:使用java反射包中的类和接口实现动态代理的goon功能

反射包:java.lang.reflect里面的三个类:InvocationHandler,Method,Proxy

2.cglib动态代理:cglib是第三方工具库,创建代理对象

cglib的原理是继承,cglib通过继承目标类,创建它的子类,在子类中重写父类中同名的方法,实现功能的修改

因为cglib是继承,重写方法,所以要求目标类不能是final的,方法也不能是final的。

cglib的要求目标类比较宽松,只要能继承就可以了

动态代理能做什么?

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

程序开发中的意思:

比如,你所在的项目中,有一个功能是其他人(公司的其他部门,其他小组的人)写好的,你可以使用。

GonNeng.class, GoNeng gn = new GonNeng(); gn.print();

你发现这个功能现在还缺点东西,不能完全满足我项目的需要,我需要在gn.pring()执行后,自己增加代码

用代理实现gn.print()调用后,增加自己的代码,而不用去改变原来的GonNeng文件

2、jdk动态代理:

JDK动态代理,必须有接口,目标类必须实现接口,没有接口时,需要使用cglib动态代理

1.反射,Method类,表示方法。类中的方法,通过Method可以执行某个方法

method.invoke();

2.JDK动态代理的实现

反射包:java.lang.reflect里面的三个类:InvocationHandler,Method,Proxy

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

代理类完成的功能:

1.调用目标方法,执行目标方法的功能

2.功能增强,在目标方法调用时,增加功能

方法原型: Object proxy:JDK创建的代理对象,无需赋值

Method method:目标类中的方法,jdk提供method对象,无需赋值

Object[] args:目标类中方法的参数,jdk提供的,无需赋值

public Object invoke(Object proxy, Method method, Object[] args)

怎么使用?1.创建类实现InvocationHandler

2.重写invoke()方法,把原来静态代理中代理类要完成的功能写在这里

2)Method类:表示方法的,确切的说就是目标类中的方法

作用:通过Method可以执行某个目标类的方法,Method.invoke();

method.invoke(目标对象,方法参数);

说明:method.invoke()就是用来执行目标方法的。

3)Proxy类:核心对象,创建代理对象。之前我们创建对象都是new类的构造方法()

现在我们使用Proxy类的方法,代替new 的使用

方法:静态方法 newProxyInstance()

作用:创建代理对象,等同于静态代理中 new TaoBao();

方法原型:

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

参数:1.ClassLoader loader 类加载器,负责向内存中加载对象的。使用反射来获取对象的ClassLoader

比如:类a, a.getClass().getClassLoader();目标对象的类加载器

2. Class<?>[] interfaces 接口,目标对象实现的接口,也是反射获取的

3. InvocationHandler h:我们自己写的,代理类要完成的功能

返回值:就是代理对象

3、实现动态代理的步骤

1.创建接口,定义目标类要完成的功能

//目标接口
public interface UsbSell {
    float sell(int amount);
}

2.创建目标类实现接口

//目标类
public class UsbKingFactory implements UsbSell {
    //目标方法
    @Override
    public float sell(int amount) {
        System.out.println("目标类中执行了目标方法");
        return 85;
    }
}

3.创建InvocationHandler接口的实现类,在invoke方法中完成代理类的功能

        1、调用目标方法 2、增强功能

//必须实现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;
        res = method.invoke(target,args);//执行目标方法
        if (res != null) {
            float price = (float) res;
            price += 25;
            res = price;
        }
        System.out.println("功能增强");
        return res;
    }
}

4.使用Proxy类的静态方法,创建代理对象,并把返回值转为接口类型

public class MainShop {
    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);

        //4.通过代理执行方法
        float price = proxy.sell(111);
        System.out.println("通过动态代理对象调用方法:" + price);
    }
}

动态代理执行流程:

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值