JDK动态代理
总结:
1.代理模式:
当一个对象不能直接使用时,可以在客户端和目标类之间直接创建一个中介,这个中介就是一个代理
2.作用:
1)控制访问:在代理中,控制是否可以调用目标对象的方法
2)功能增强:可以在完成目标对象的调用时,附加一些额外的功能。这些额外的功能就是功能增强
3.代理的实现方式:
1.静态代理:代理类是手工实现的Java文件,同时代理的目标对象是规定的
1)优点:容易理解使用方便
2)缺点:在目标类比较多的时候,会产生大量的代理类,到接口改变时,影响目标类的代码实现,需要修改代码,影响较多。
2.动态代理:
1)不用创建代理类
2)可以给不同的目标类随时创建代理
详细说明:
JDK动态代理
动态代理:基于反射机制
1代理
代购,中介,商家等等
比如有一个厂家要卖衣服,可以卖给任何一个人,淘宝商家,实体店(代理)
淘宝店铺(代理):帮助这个生产厂家卖衣服,淘宝是厂家的代理,淘宝是代替厂家卖衣服的功能。
代理的特点:
1.淘宝和厂家他们要做的事情是一样的,卖衣服
2.淘宝是厂家的代理,厂家是目标。
3.顾客--淘宝--厂家
4。淘宝是代理,不能白干活,需要获取利润
为什么要找淘宝:
1.淘宝方便,不用去找生产厂家
2.用户没有能力直接从厂家直接卖衣服
买东西都是商家卖,商家就是某一种商品的代理,你个人买东西是接触不到厂家的
2.在开发中,你有A类本来是调用C类的方法完成某种功能
但是A不能直接调用C类
现在在A类和C类中间创建一个B类
B类就相当于一个代理让B类访问C类
实际例子:登录,注册需要验证码,验证码是手机短信
中国移动中国联通发送短息
中国移动,中国联通的子公司,或者关联公司她们面向社会体用发送短信业务
张三项目发送短信------子公司,或者关联公司-----中国移动,中国联通
代理模式:
代理模式是指:为其他对象提供一种代理以控制这个对象访问,在某些情况下,一个对象不适合或者不能直接引用另一个对象,尔代理对象可以在客户和目标对象之间起到中介作用
使用代理模式的作用
1.功能增强:在原有的功能的基础上,增加了额外的功能。新增加的功能,叫做功能增强
2.控制访问:代理类不让你访问目标,例如商家不让你直接接触厂家
实现代理的方式
1:静态代理
1)代理类是自己手动实现 的,自己创建一个Java类表示代理类
2)同时你所代理的的目标类是确定的
特点:实现简单,容易理解
缺点:当目标类增加了,代理类可能也需要成倍增加,代理类数量过多
当你的接口中功能增加了,或者修改了,会影响众多的实现类,目标类,代理都需要修改,影响比较多。
2:动态代理:
在静态代理中目标类很多的时候,可以使用动态代理,避免静态代理的缺点。
动态代理中目标类即使很多,1)代理类的数量可以很少2)当你修改了接口中的方法是时,不会影响代理类
动态代理:在程序执行中,使用jdk的反射机制,创建代理类的对象,并动态的指定代理目标类
换句话:动态代理是一种创建Java对象的能力,让你不用创建TAOBAO类,就可以创建代理类的对象
在Java中,想要创建对象:
1.创建类文件,Java文件编译为class文件
2.使用构造方法,创建类的对象
动态代理的实现:1.jdk动态代理:使用Java反射包中的类和接口的事项动态代理的功能
反射包Java.lang.reflect,里面的三个类:InvocationHandler,Method,proxy
2.cglib动态代理:cglib是第三方的工具库:创建代理类
cglib的原理是继承,cglib通过继承目标类,创建它的子类,在子类中重写父类的同 名方法,实现功能的修改。因为cglib时继承,重写方法,所以要求目标类不能是final的,方法也不能是final,cglib的要求目标类比较宽松,只要可以继承就可以,cglib在很多框架中使用,比如mybatis,spring中
在介绍动态代理之前我们先看一个静态代理的例子:
1.首先我们先创建一个u盘的接口实现卖东西的方法:
package com.zzjm.Service;
//定义一个接口实现卖u盘的方法
//表示功能的,商家和厂家都要执行
public interface UsbSell {
//定义参数方法,amount表示购买数量;返回值表示u盘价格;
float sell(int amount);
}
2.我们创建一个目标类来实现接口卖东西的方法:
package com.zzjm.factory;
import com.zzjm.Service.UsbSell;
//表示商家的价格
//厂家继承接口的方法实现卖u盘的方法
public class SanUsb implements UsbSell {
//参数表示卖出优盘的数量
//返回值是总价
@Override
public float sell(int amount) {
float pire = 0;
if (amount<100) {
pire = amount * 85.0f;//表示如果购买数量小于100商家卖出一个是85元
}else if(amount>=100){
pire = amount * 75.0f;//表示如果购买数量大于100商家卖出一个是75元
}
return pire;//返回的价格是购买u盘的总价
}
}
3.我们床架代理类实现功能增强(给u盘增加价格)
package com.zzjm.TaoBao;
import com.zzjm.Service.UsbSell;
import com.zzjm.factory.SanUsb;
public class taobaosell implements UsbSell {
private UsbSell usbSell=new SanUsb();//实例化厂家(目标类)向厂家进货
@Override
public float sell(int amount) {
//卖给用户
float pire= usbSell.sell(amount);
pire=pire+amount*10;//没见商品加价10元
return pire;
}
}
4.下面我们模仿顾客购买u盘:
package com.zzjm;
import com.zzjm.TaoBao.taobaosell;
import java.lang.reflect.Proxy;
public class MyApp {
public static void main(String[] args) {
taobaosell taobaosell=new taobaosell();
float pirce=taobaosell.sell(10);
System.out.println("需要支付的价格是"+pirce);
}
}
JDK动态代理:
jdk动态代理采用反射机制来实现:
1.反射:Method类,表示方法,类中的方法,通过Method可以执行这个方法。
2.jdk动态代理的实现
反射包java.lang.reflect,里面有三个类:InvocationHandler,Mathod,porxy
1.InvocationHandler:(调用处理器),就一个invoke()方法
invoke()方法:表示代理对象要执行的功能代码,你的代理类要完成的功能就写在这里
代理类要完成的功能:
1.调用目标方法:
2.功能增强,在调用目标方法的同时,增强功能。
方法原理:
参数
Obiect proxy:jdk创建的代理对象,无需赋值
Method method:目标类中的方法,jdk提供method对象
Object[]args:目标类中的方法参数,jdk提供
public Object invoke(Obiect proxy,Method method,Object[]args)
InvocationHandler接口:表示你的代理要干什么,
怎么用:1.创建类实现的接口InvocationHandler
2.重写invoke方法,把原来静态代理中代理要完成的功能,写在这。
Method类:表示这个方法,确切说就是目标类中的方法
作用:通过这个method可以执行某个目标类的方法,Method.invoke();
method.invoke(目标对象,方法参数)
Object obiect=method.invoke(sayHello,"张三");
说明:method.invoke()就是用来执行目标方法的,等于静态代理中的
float pirce=taobaosell.sell(10);
proxy类:核心的对象,创建代理类,之前创建的对象都是new 类的构造方法
而现在我们使用proxy类的方法,代替new的使用
方法:静态方法newProxyInstance()
作用:床架代理对象,等同于静态代理中的Taobao taobao=new TaoBao()
参数:
1.ClassLoader loader类加载器,负责向内存中加载对象的,使用反射机制获取对象ClassLoader loader
2. Class<?>[] interfaces:接口,目标对象的实现接口,也是反射获取
3. InvocationHandler h:我们自己写的,代理类要完成的功能。
public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h)
JDK动态代理的示例:
1.跟静态代理一样首先创建一个实现买东西的接口(方法参数为购买的数量):
package com.zzjm.Service;
public interface Usbsell {
float sell(int amount);
}
2.创建目标类:
package com.zzjm.factory;
import com.zzjm.Service.Usbsell;
public class UsbKingfactory implements Usbsell {
@Override
public float sell(int amount){
float pirce=0;
pirce=amount*85;
return pirce;
}
}
3.用动态代理的方式实现目标增强的功能(代替了静态代理的淘宝,但是一样实现了功能增强):
package com.zzjm.handler;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
//必须实现InvocationHandler接口,来完成代理类要做的功能(1.调用方法,2功能增强)
public class MysellHandler implements InvocationHandler {
private Object trag=null;
//动态代理目标是活动的,需要传入进来
//传入是谁,谁就是代理对象
public MysellHandler(Object trag) {
//给目标对象赋值
this.trag = trag;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws InvocationTargetException, IllegalAccessException {
Object res=null;
//向厂家发送订单,告诉厂家我买了u盘,厂家发货
//float pire= usbSell.sell(amount);
//商家需要加价,也就是功能增强
//pire=pire+amount*10;//每件商品加价10元
//return pire;
res=method.invoke(trag,args);//执行目标方法。
if (res!=null){
Float pirce=(Float)res;
pirce=pirce+25;
res=pirce;
}
System.out.println("====="+res);
return res;
}
}
4.测试购买商品:
import com.zzjm.handler.MysellHandler;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
public class MyAp {
public static void main(String[] args) {
//创建代理对象,使用Proxy;
//1.创建目标对象
Usbsell factory=new UsbKingfactory();
//2.创建invocationHandler对象
InvocationHandler invocationHandler=new MysellHandler(factory);
//创建代理执行方法
Usbsell proxy=(Usbsell) Proxy.newProxyInstance(factory.getClass().getClassLoader(),factory.getClass().getInterfaces(),invocationHandler);
float price=proxy.sell(2);
System.out.println("总价"+price);
}
}