详解JDK动态代理使用及原理

2022-07-25 14:48:33

一.代理模式

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

二.使用代理模式的作用

  1. 功能增强:在不改变目标方法的前提下,通过代理增加额外的功能。
  2. 控制访问:代理类不让你直接访问目标

三.实现代理的方式

1.静态代理

(1)特点

a.代理是你手工实现的,自己创建一个Java类,代表代理类
b.你要代理的目标类是明确的
c.实现简单,容易理解

(2)举例(用户购买商品的行为)

用户:客户端类
商家:代理,代理某个商品
厂家:目标类

实现步骤:
a.创建一个接口,定义卖东西的行为
b.创建厂家类,实现步骤a中的接口
c.创建商家类,也就是代理,实现步骤a中的接口
d.创建用户类,调用商家类的方法购买东西

代理类实现的功能:
a.调用目标类的方法
b.功能增强

(3)缺点

当项目中目标类和和代理类很多的时候
a.当目标类增加时,代理类可能要成倍的增加
b.当接口中功能增加或修改时,会影响众多的代理类和目标类

2.动态代理

(1)特点

在程序运行过程中,通过jdk的反射机制,创建代理类对象,并动态的指定其目标类。
即就是一种创建java对象的能力,让你不用手动去创建代理类。

(2)实现

jdk动态代理

使用Java反射包中的类和接口实现动态代理
java.lang.reflect中有三个类/接口:InvocationHandler,Method,Proxy

a. InvocationHandler接口(调用处理器)

其中只有一个方法:invoke() :代理对象要执行的功能代码
方法原型
public object invoke(object proxy,Method method,Object args)
参数
object proxy : jdk创建的代理对象
Method method:目标类中的方法,是jdk提供method对象的
Object[] args:目标类中方法的参数,jdk提供的
使用
(1)创建类实现InvocationHandler接口
(2)重写invoke()方法,将代理类要实现的功能写入invoke()中

b. Method类

作用:执行某个目标类的方法

method.invoke(目标对象,方法的参数);
method.invole(service,"张三");

c. Proxy类

作用:创建代理对象
方法:静态方法public static Object newProxyInstance()

//方法原型//该方法返回值就是代理对象publicstaticObjectnewProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h)

参数说明:

ClassLoader loader
类加载器,向内存中加载对象,通过反射机制获取对象的ClassLoader,是目标对象的类加载器。

//a类
a.getClass().getClassLoader();

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

InvocationHandler h
是我们自己写的代理类要实现的功能

d.实现步骤

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

packagecom.xhy.service;//目标接口//售卖u盘的功能publicinterface usbSell{floatsell(int amount);}

2.创建目标类实现接口

packagecom.xhy.factory;importcom.xhy.service.usbSell;//目标类//u盘厂家实现卖u盘的功能publicclass usbkingFactoryimplements usbSell{@Override//目标方法//amount是购买数量publicfloatsell(int amount){System.out.println("目标类执行了sell目标方法!");return65.0f;//u盘的厂家价格}}

3.创建InvocationHandler的实现类,在invoke方法中实现代理对象的功能

packagecom.xhy.handler;importjava.lang.reflect.InvocationHandler;importjava.lang.reflect.Method;//实现InvocationHandler接口,完成代理类的功能//1.实现目标方法//2.功能增强publicclass mysellHandlerimplementsInvocationHandler{privateObject target=null;//动态代理,目标对象是动态的,是由你自己传入的,传入的对象是谁,就给谁创建代理publicmysellHandler(Object target){this.target= target;}@OverridepublicObjectinvoke(Object proxy,Method method,Object[] args)throwsThrowable{Object res=null;//1.执行目标方法//向厂家发送订单,厂家发货
        res= method.invoke(target,args);//厂家的价格//2.功能增强//商家(代理)需要加价,并且赠送买家优惠券if(res!=null){Float price=(Float) res;
            price= price+30;
            res= price;}System.out.println("商家赠送了一张五元优惠券");//商家加价后的新价格return res;}}

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

importcom.xhy.factory.usbkingFactory;importcom.xhy.handler.mysellHandler;importcom.xhy.service.usbSell;importjava.lang.reflect.Proxy;publicclass mainShop{publicstaticvoidmain(String[] args){//创建代理对象,使用Proxy//1.创建目标类对象
        usbkingFactory factory=newusbkingFactory();//2.创建InvocationHandler对象
        mysellHandler handler=newmysellHandler(factory);//3.创建代理对象
        usbSell proxy=(usbSell)Proxy.newProxyInstance(factory.getClass().getClassLoader(),
                factory.getClass().getInterfaces(),
                handler);//4.通过代理对象,调用目标方法//商家加价后的价格float price= proxy.sell(1);System.out.println("通过代理对象调用了目标方法(商家向厂家发送了订单):"+price);}}//呼,好累啊好累啊

5.执行结果

目标类执行了sell目标方法!
商家赠送了一张五元优惠券
通过代理对象调用了目标方法(商家向厂家发送了订单):95.0
  • 作者:xhy123_
  • 原文链接:https://blog.csdn.net/xhy123_/article/details/120994823
    更新时间:2022-07-25 14:48:33