1、 什么是代理模式?
当一个对象不能直接使用,可以在客户端和目标对象之间创建一个中介,这个中介就是代理
作用:
1.控制访问:在代理模式中,控制是否可以调用目标对象的方法
2.功能增强:可以在完成目标对象的调用时,附加一些额外的功能,这些额外的功能叫做功能增强
代理的实现方式:
1.静态代理:代理类是手动实现的一个java文件,同时代理的目标对象是固定的
优点:容易理解,使用方便
缺点:在目标类比较多的时候,会产生大量的代理类;当接口改变时,所影响的目标类和代理类比较多
2.动态代理:使用反射机制,在程序的执行中,创建代理类对象
优点:不用创建代理类文件,代理的目标类是活动的,可设置的,可以给不同的目标随时创建代理
动态代理的实现:
1.jdk动态代理:使用java反射包中的类和接口实现动态代理的goon功能
反射包:java.lang.reflect里面的三个类:InvocationHandler,Method,Proxy
2.cglib动态代理:cglib是第三方工具库,创建代理对象
cglib的原理是继承,cglib通过继承目标类,创建它的子类,在子类中重写父类中同名的方法,实现功能的修改
因为cglib是继承,重写方法,所以要求目标类不能是final的,方法也不能是final的。
cglib的要求目标类比较宽松,只要能继承就可以了
动态代理能做什么?
可以在不改变原来目标方法功能的前提下,在代理中增强自己的功能代码。
程序开发中的意思:
比如,你所在的项目中,有一个功能是其他人(公司的其他部门,其他小组的人)写好的,你可以使用。
GonNeng.class, GoNeng gn = new GonNeng(); gn.print();
你发现这个功能现在还缺点东西,不能完全满足我项目的需要,我需要在gn.pring()执行后,自己增加代码
用代理实现gn.print()调用后,增加自己的代码,而不用去改变原来的GonNeng文件
2、jdk动态代理:
JDK动态代理,必须有接口,目标类必须实现接口,没有接口时,需要使用cglib动态代理
1.反射,Method类,表示方法。类中的方法,通过Method可以执行某个方法
method.invoke();
2.JDK动态代理的实现
反射包:java.lang.reflect里面的三个类:InvocationHandler,Method,Proxy
1)InvocationHandler(调用处理器)是一个接口,就一个方法:invoke();表示代理对象要执行的功能代码。你的代理 类要完成的功能就写在invoke()方法中
代理类完成的功能:
1.调用目标方法,执行目标方法的功能
2.功能增强,在目标方法调用时,增加功能
方法原型: Object proxy:JDK创建的代理对象,无需赋值
Method method:目标类中的方法,jdk提供method对象,无需赋值
Object[] args:目标类中方法的参数,jdk提供的,无需赋值
public Object invoke(Object proxy, Method method, Object[] args)
怎么使用?1.创建类实现InvocationHandler
2.重写invoke()方法,把原来静态代理中代理类要完成的功能写在这里
2)Method类:表示方法的,确切的说就是目标类中的方法
作用:通过Method可以执行某个目标类的方法,Method.invoke();
method.invoke(目标对象,方法参数);
说明:method.invoke()就是用来执行目标方法的。
3)Proxy类:核心对象,创建代理对象。之前我们创建对象都是new类的构造方法()
现在我们使用Proxy类的方法,代替new 的使用
方法:静态方法 newProxyInstance()
作用:创建代理对象,等同于静态代理中 new TaoBao();
方法原型:
public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h)
参数:1.ClassLoader loader 类加载器,负责向内存中加载对象的。使用反射来获取对象的ClassLoader
比如:类a, a.getClass().getClassLoader();目标对象的类加载器
2. Class<?>[] interfaces 接口,目标对象实现的接口,也是反射获取的
3. InvocationHandler h:我们自己写的,代理类要完成的功能
返回值:就是代理对象
3、实现动态代理的步骤
1.创建接口,定义目标类要完成的功能
//目标接口
public interface UsbSell {
float sell(int amount);
}
2.创建目标类实现接口
//目标类
public class UsbKingFactory implements UsbSell {
//目标方法
@Override
public float sell(int amount) {
System.out.println("目标类中执行了目标方法");
return 85;
}
}
3.创建InvocationHandler接口的实现类,在invoke方法中完成代理类的功能
1、调用目标方法 2、增强功能
//必须实现Invocationhandler接口,完成代理类要做的功能(1.调用目标方法 2.完成目标增强)
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 = null;
res = method.invoke(target,args);//执行目标方法
if (res != null) {
float price = (float) res;
price += 25;
res = price;
}
System.out.println("功能增强");
return res;
}
}
4.使用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 proxy = (UsbSell)Proxy.newProxyInstance(factory.getClass().getClassLoader(), factory.getClass().getInterfaces(), handler);
//4.通过代理执行方法
float price = proxy.sell(111);
System.out.println("通过动态代理对象调用方法:" + price);
}
}
动态代理执行流程: