JDK动态代理

代理模式

Java的设计模式中有一项设计模式叫做代理模式

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

作用:

  • 功能增强:在原有的功能上,增强了额外的功能。
  • 控制访问:代理类不让你访问目标

实现代理的方式:

  • 静态代理

  • 动态代理

静态代理:

  • 针对每个被代理对象写一个代理类,操作不够优雅
  • 特点:
    • 实现简单
    • 容易理解。
  • 缺点:
    • 当目标类增加了,代理类可能也需要成倍的增加。代理类数量过多。
    • 当接口中功能增加了或者修改了,会影响众多的实现类,厂家类,代理都需要修改。影响比较多。

例如:模拟一个用户购买u盘的行为。

​ 用户:客户端类

​ 商家: 代理,代理某个品牌的u盘。

​ 厂家: 目标类。

三者的关系: 用户(客户端)—商家(代理)—厂家(目标)商家和厂家都是卖u盘的,他们完成的功能是一致的,都是卖u盘。

实现步骤:

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

代理类完成的功能:

  1. 目标类中方法的调用
  2. 功能增强
/* UsbSell接口 */

// 表示功能的,厂家,商家都要完成的功能
public interface UsbSell {

    // 定义方法,参数amount:表示一次购买的数量
    // 返回值表示一个U盘的价格
    float sell(int amount);

}
/* UsbKingFactory类 --- 厂家 */
import com.sproxy.service.UsbSell;

// 目标类:金士顿厂家,不接受用户单独购买
public class UsbKingFactory implements UsbSell {
    @Override
    public float sell(int amount) {
        //一个128G的u盘是85元。
        //后期根据amount ,可以实现不同的价格,例如10000个,单击是80 ,50000个75

        return 85.0f;
    }
}
/* TaoBao类 --- 商家 */
import com.sproxy.factory.UsbKingFactory;
import com.sproxy.service.UsbSell;

// Taobao是一个商家,代理金士顿U盘的销售
public class TaoBao implements UsbSell {

    // 声明商家代表的厂家具体是谁
    private UsbKingFactory factory = new UsbKingFactory();

    @Override
    // 实现卖U盘的功能
    public float sell(int amount) {
        // 向厂家发送订单,告诉厂家我卖了U盘,厂家发货
        float price = factory.sell(amount);  // 厂家的价格
        // 商家加价,赚取代理费,增加价格
        price += 25;
        // 增加后的价格
        return price;
    }
}

/* 用户类 */
import com.sproxy.shangjia.TaoBao;

public class ShopMain {

    public static void main(String[] args) {
        // 创建代理的商家taobao对象
        TaoBao taoBao = new TaoBao();
        float price = taoBao.sell(1);
        System.out.println("通过taobao商家,购买的U盘价格为:" + price);

    }
}

动态代理:

dynamic 动态的

  • 可以根据接口动态的生成代理类
  • 动态代理是指代理类对象在程序运行时由JVM根据反射机制动态生成的。动态代理不需要定义代理类的.java源文件。
  • 动态代理其实就是jdk运行期间,动态创建class字节码并加载到JVM
  • 动态代理的实现方式常用的有两种:使用JDK动态代理,与通过cglib动态代理。

cglib动态代理

CGLIB(Code Generation Library)是一个开源项目。是一个强大的,高性能,高质量的Code 生成类库,它可以在运行期扩展Java类与实现Java接口。它广泛的被许多AOP的框架使用,例如Spring AOP

cglib是第三方的工具库,创建代理对象。

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

CGLIB代理的生成原理是生成目标类的子类,而子类是增强过的,这个子类对象就是代理对象。所以,使用CGLIB生成动态代理要求自标类必须能够被继承,即不能是 final的类。

对比:

  • 使用JDKProxy实现代理,要求目标类与代理类实现相同的接口。若目标类不存在接口,则无法使用该方式实现
  • 对于无接口的类,要为其创建动态代理,就要使用CGLIB来实现。
  • cglib经常被应用在框架中,例如SpringHibernatemybatis等。cglib 的代理效率高于jdk。对于cglib一般的开发中并不使用。

jdk的动态代理

jdk动态代理是基于Java 的反射机制实现的。使用 jdk中接口和类实现代理对象的动态创建。

jdk的动态要求目标对象必须实现同一接口,这是Java 设计上的要求。

jdk1.3以来,Java语言通过java.lang.reflect包提供三个类支持代理模式Proxy, MethodInovcationHandler.

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

InvocationHandler接口

(调用处理器)

需要重写方法invoke ()

  • invoke() : 表示代理对象要执行的功能代码。你的代理类要完成的功能就写在invoke ()方法中。
  • 代理类完成的功能:
    1. 调用目标方法,执行目标方法的功能
    2. 功能增强,在目标方法调用时, 增加功能。

方法原型:

public object invoke (object proxy, Method method, Object[] args)
    
参数:
    + object proxy:   jdk创建的代理对象,无需赋值。
    + Method method:  目标类中的方法,jdk提供method对象的
    + Object[] args:  目标类中方法的参数,jdk提 供的。

Method类

表示方法的,确切 的说就是目标类中的方法。

作用:

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

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

    反射中method.invoke (helloService,"何鼎东") ;

  • 说明:

    • method.invoke() 就是用来执行目标方法的,等同于静态代理中的

      //向厂家发送订单,告诉厂家,我买了u盘,厂家发货
      float price = factory . sell (amount) ; //厂家的价格。
      

Proxy类

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

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

方法:

  • 静态方法 newProxyInstance()
  • 作用是 : 创建代理对象,等同于静态代理中的TaoBaotaoBao=newTaoBao();

方法原型:

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

参数:
	1.ClassLoaderloader  目标对象的类加载器,负贲向内存中加载对象的。使用反射获取对象的
	2. Class<?>[] interfaces:  接口,目标对象实现的接口,也是反射获取的。
	3. InvocationHandler h :  自己写的代理类要完成的功能。
返回值:就是代理对象

实现动态代理的步骤

  1. 创建接口,定义目标类要完成的功能.
  2. 创建目标类实现接口
  3. 创建InvocationHandler接口的实现类,在invoke方法中完成代理类的功能
    1. 调用目标方法
    2. 增强功能
  4. 创建代理对象,使用Proxy类的静态方法。并把返回值转为接口类型。
public interface UsbSell {

    float sell(int amount);
}

import com.dproxy.service.UsbSell;

// 目标类
public class UsbKingFactory implements UsbSell {
    @Override
    public float sell(int amount) {
        // 目标方法
        System.out.println("目标类中的sell目标方法执行了...");
        return 85.0f;
    }
}
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

// 必须实现InvocationHandler接口来完成代理类的功能
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;
        // 向厂家发送订单,告诉厂家我卖了U盘,厂家发货
        // float price = factory.sell(amount);  // 厂家的价格
        res = method.invoke(target, args);  // 执行目标方法

        if (res!=null){
            float price = (float)res;
            // 商家加价,赚取代理费,增加价格
            price += 25;
            res = price;
        }

        // 增加后的价格
        return res;

    }
}
import com.dproxy.factory.UsbKingFactory;
import com.dproxy.handler.MySellHandler;
import com.dproxy.service.UsbSell;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.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 porxy = (UsbSell) Proxy.newProxyInstance(factory.getClass().getClassLoader(),
                factory.getClass().getInterfaces(),
                handler);

        // 4.通过代理执行方法
        float price = porxy.sell(1);

        System.out.println("通过动态代理调用方法的:" + price);
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值