使用JDK反射机制,创建对象的能力,创建的是代理类的对象,而不用你创建类,不用写java文件 动态:在程序执行时,调用JDK提供的方法才能创建代理类的对象 JDK动态代理,必须有接口,目标类必须实现接口,没有接口时需要使用cglib动态代理
在不改变原来的目标方法功能的前提下,可以在代理中增强自己的功能代码
代理:在我们生活之中就有体会,代购,中介,换IP,商家等等
**优点>>**实现简单 容易理解
缺点>> \当你的项目中.目标类和代理类很多的时候,有以下缺点
模拟一个用户购买u盘的行为。 用户是客户端类 商家:代理,代理某个品牌的u盘。 厂家:目标类。 三者的关系: 用户(客户端)—商家(代理)—厂家(目标) 商家和厂家都是卖u盘的,他们完成的功能是一致的,都是卖u盘。 实现步骤
代理类完成的功能:
所属我们只有一个代理商,我们实际上可以写多个代理商,
使用JDK的反射机制,创建对象的能力,创建的时代理类的对象.而不用我们创建类的文件.
什么叫动态?在程序执行时,调用JDK提供的方法才能创建代理类的对象
静态代理中目标很多的时候,可以使用动态代理,避免静态代理的缺点
在执行过程中,使用了JDK的反射机制,创建代理类对象,并动态的指定要代理目标类
换句话说:动态代理是一种创建JAVA对象的能力,让你不用创建淘宝类,就能创建代理类对象,
在java中,要想创建对象
1.动态代理是指代理类对象在程序运行时由JVM根据反射机制动态生成的,动态代理不需要定义代理类的,java源文件
2.动态代理其就是JDK运行期间,动态创建Class字节码并加载到JVM
3.动态代理的实现运行常用两种方式:使用JDK
代理,与通过CGLlB
动态代理。
JDK动态代理(理解),使用java反射包的类和接口实现动态代理的功能
反射包java.lang.reflect
里面有三个类 : InvocationHandler
,Method
, Proxy
InvocationHandler , Method, Proxy.
1) InvocationHandler`
InvocationHandler
接口(调用对象); 就是一个方法invoke
()
invoke
(): 表示代理对象要执行的功能代码, 要完成的功能就写在invoke()方法中
代理类完成的功能
参数:
Object proxy:jdk创建的代理对象,无需赋值。
Method method:目标类中的方法,jdk提供method对象的
Object[] args:目标类中方法的参数, jdk提供的。
public Object invoke(Object proxy, Method method, Object[] args)
InvocationHandler
接口:表示你的代理要干什么。
怎么用: 1.创建类实现接口InvocationHandler
2.重写invoke()方法, 把原来静态代理中代理类要完成的功能,写在这。
表示方法的, 确切的说就是目标类中的方法。
作用:
通过Method可以执行某个目标类的方法,Method.invoke();
method.invoke(目标对象,方法的参数)
Object ret = method.invoke(service2, "李四");
说明: method.invoke()就是用来执行目标方法的,等同于静态代理中的
//向厂家发送订单,告诉厂家,我买了u盘,厂家发货
float price = factory.sell(amount); //厂家的价格。
核心的对象,创建代理对象。之前创建对象都是 new 类的构造方法() 现在我们是使用Proxy类的方法,代替new的使用。
方法: 静态方法 newProxyInstance()
作用是: 创建代理对象, 等同于静态代理中的TaoBao taoBao = new TaoBao();
参数:
ClassLoader loader
类加载器,负责向内存中加载对象的。 使用反射获取对象的ClassLoader
类a , a.getCalss().getClassLoader()
, 目标对象的类加载器
Class<?>[] interfaces
: 接口, 目标对象实现的接口,也是反射获取的。
InvocationHandler
h : 我们自己写的,代理类要完成的功能。
返回值:就是代理对象
public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)
4.使用Proxy类的静态方法,创建代理对象。 并把返回值转为接口类型。
第一步
public interface UsbSell {
float sell(int amount);
}
第二步
public class UsbKingFactory implements UsbSell {
@Override
public float sell(int amount) {
System.out.println("目标类中,执行了sell目标方法");
return 85.02f;
}
}
我们写了接口类,定义了功能,写了代理类,实现了接口功能,按照以前的操作,现在就需要写一个真正的代理类,创建对象.
第三步: 创建了
Invocationhandler
实现类,在invoke()方法中完成代理类de对象
public class MyHandle implements InvocationHandler {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
return null;
}
}
代理类的实现方法上进行修改
//之前的代理类
public class TaoBao implements usbSell {
// 声明 商家代理的厂家具体是谁
private UsbKingFactory factory =new UsbKingFactory();
@Override
// 实现销售U盘功能
public float sell(int amount) {
// 向厂家发送订单,告诉厂家,我买了U盘,厂家发货
// 发送给工厂,我需要的订单,返回报价
float price = factory.sell(amount);
// 商家需要加价也就是代理要增加价格
price = price + 25;
//在目标类的方法调用后,你做的其他功能,都是增强的意思
System.out.println("淘宝再给你返回一个优惠券,或者红包");
// 增加的价格
return price;
}
}
调用目标的方法
//传入是谁的对象,就给谁创建代理
public MyHandle(Object target) {
this.target = target;
}
public Object invoke(Object proxy, Method method, Object[] args){
Object res =null;
// 向厂家发送订单,告诉厂家,我买了U盘,厂家发货
// 发送给工厂,我需要的订单,返回报价
// float price = factory.sell(amount);
res = method.invoke(target,args); //待执行目标方法,执行后返回值
//增强的方法 res
}
第四步: 使用Proxy类的静态方法,创建代理对象,并把返回值转换成接口类型
创建一个MainShop类.
public class MainShop {
public static void main(String[] args){
// 1.创建对象,使用Proxy
// 2.创建目标对象
UsbSell factory = new UsbKingFactory();
// 3.创建Invocationhandler对象
InvocationHandler myHandle = new MyHandle(factory);
// 4.创建代理对象
UsbSell proxy = (UsbSell) Proxy.newProxyInstance(factory.getClass().getClassLoader(),
factory.getClass().getInterfaces(),
myHandle);
// 通过代理执行方法
float price = proxy.sell(1);
System.out.println("通过动态代理对象,调用方法:" +price);
}
}
我们先复习一下,Proxy类,实现动态代理的流程,使用返回指定接口的代理类实例,
我们此时debug一下程序,在invok实现类中打一个断点
此时我们再观察,代理对象MyHandler里面的invoke方法的参数