jdk动态代理

原文链接:jdk动态代理 – 编程屋

目录

1 前言

2 代理方式

        2.1 静态代理

         2.1.1 静态代理实现

        2.2 动态代理

         2.2.1 动态代理实现的几种方式

         2.2.2 实现动态代理


1 前言

        代理模式:是指为其他对象提供一种代理以控制对这个对象的访问,在某些情况下,一对象不适合或者不能直接引用另外一个对象,而代理对象可以在客户类和目标对象之间起到中介的作用。

        使用代理对象,是为了在不修改目标对象的基础上,增强主业务逻辑。客户类真正想要访问的对象是目标对象,但客户真正能够访问的是代理对象,客户类对目标对象的访问是通过访问代理类来实现的。

作用:

1 功能增强:在你原有的功能上,增加了额外的功能,新增加的功能叫做功能增强

2 控制访问:代理类不让你访问目标

2 代理方式

        2.1 静态代理

1)代理类是自己手工实现的

2)自己所需要代理的对象是确定的

         2.1.1 静态代理实现

步骤1 :定义一个卖u盘的接口

步骤2:创建一个厂家的类,实现步骤一中卖u盘的方法

步骤3:创建商家(代理),实现步骤一中的接口

步骤4:创建客户端类,调用商家方法买u盘

代码实现:

步骤一:定义一个卖u盘的接口

public interface UsbSell {

    /**
     * 定义一个方法 厂家,商家都要用完成的功能
     * @param amount 购买的数量
     * @return
     */
    float sell(int amount);
}

步骤2:创建一个厂家的类,实现步骤一中卖u盘的方法

//目标类 厂家只向中间商供货,不会想个体小商户供货
public class UsbFactory implements UsbSell {
    @Override
    public float sell(int amount) {
        //定义一个U盘的价格是65元
        float price = 65.0f;
        return amount*price;
    }
}

步骤3:创建商家(代理),实现步骤一中的接口

//代理类-----中间商
public class TaoBao implements UsbSell {

    //代理的是金士顿 定义目标厂家类
    private UsbFactory usbFactory =  new UsbFactory();

    @Override
    public float sell(int amount) {
        //调用目标方法
        float price = usbFactory.sell(amount);

        price =  (price + 15)*amount;
        return price;
    }
}

步骤4:创建客户端类,调用商家方法买u盘

    @Test
    public void test7(){
        TaoBao taoBao = new TaoBao();
        float sell = taoBao.sell(80);
        System.out.println("***总金额****"+sell); //***总金额****417200.0
    }

可见,我们通过代理中间商去购买u盘的时候,被中间商每个u盘都赚了15元的差价。

我们可以发现,这个加价格的这个功能时我们在调用了目标类之后进行的,其实这一步就相当于我们一个功能的增强(代理类在完成功能时会进行一个增强),同时我们也可进行一些其他的功能增强,比如:返回优惠券或者红包,只要是在我们原有功能完成之后进行的功能都属于功能增强。

静态代理优缺点:

优点:实现方便简单,容易理解

缺点:目标类增加时,代理会增加。接口功能修改了商家和代理类都有改动

        2.2 动态代理

        动态代理:在程序执行过程中,使用jdk的反射机制,创建代理类对象,并动态的指定要代理的目标类。(动态代理是一种创建Java对象的能力,省去了我们自己创建代理类对象)

Spring Aop底层实现,是通过jdk动态代理或者CGlib代理在运行时期在对象初始化阶段织入代码的

jdk动态代理是基于接口实现的

CGlib是基于类的集成实现的

2.2.1 动态代理实现的几种方式

1 cglib动态代理:cglib是第三方的工具库,创建代理对象,cglib的原理是继承,cglib通过继承目标类,创建它的子类,在子类中重写父类中重名的方法,实现功能的修改

因为cglib是继承,重写方法,所以需要要继承的类不能是final的,重写的方法也不能是final的。cglib在mybatis,spring中的框架中都有使用

2 jdk的动态代理:使用Java反射包中的类和接口实现动态代理的功能。反射包:Java lang reflect 三个类:InvocationHandler ,Method,Proxy

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

代理类完成的功能:

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

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

方法原型:

参数:

Object proxy:jdk创建的代理对象,无需赋值

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

Object[] args:目标类中方法的参数

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

2)Method:表示方法的(目标类中的方法)

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

注意:此处的invoke方法和InvocationHandler类中的invoke方法不是同一个

3)Proxy类:创建代理对象,不在通过之前那种new 类的构造方法来创建对象了,而是使用Proxy类中的方法,代替new的使用

方法;静态方法 newProxyInstance()

参数:

ClassLoader loader 类加载器:负责向内存中加载对象的。使用反射获取对象的ClassLoader(比如:类B>>B.getCalss().getClassLoader())目标对象的类加载器

Class<?> interface:目标对象实现的接口,也是通过反射获取的

InvocationHandler h:代理类要完成的功能

public static Object newProxyInstance(ClassLoader loader,

Class<?> interface,InvocationHandler h)

2.2.2 实现动态代理

步骤一:创建接口,定义目标类要完成的功能

public interface UsbSell {

    float sell(int amount);
}

步骤二:创建目标类实现接口

public class UsbSellFactory implements UsbSell{

    @Override
    public float sell(int amount) {
        System.out.println("进入目标类中执行的方法");
        return 65.0f*amount;
    }
}

步骤三:创建InvocationHandler接口的实现类,在invoke方法中完成代理的功能(1 调用目标方法2增强功能)

以上只是部分内容,为了维护方便,本文已迁移到新地址:jdk动态代理 – 编程屋

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值