Java动态代理
代理模式:代理(Proxy)是一种设计模式,提供了对目标对象另外的访问方式;即通过代理对象访问目标对象。
这样做的好处是:可以在目标对象实现的基础上,增强额外的功能操作,即扩展目标对象的功能。
一、静态代理
被代理的接口
public interface UsbProducer {
float sell(int num);
}
目标类
/**
* 目标类:实现了生产Usb的接口
*/
public class KingUsbFactory implements UsbProducer{
@Override
public float sell(int num) {
int price = 88;
System.out.println("目标类执行了方法---");
return num*price;
}
}
代理类
/**
* TaoBao是KingUserFactory的代理类
*/
public class TaoBao implements UsbProducer{
KingUsbFactory kingUsbFactory;
//通过构造方法传入目标对象
public TaoBao(KingUsbFactory kingUsbFactory) {
this.kingUsbFactory = kingUsbFactory;
}
@Override
public float sell(int num) {
//调用目标类
float price = kingUsbFactory.sell(num);
//功能增强
price += 25*num;
System.out.println("代理类执行了方法---");
return price;
}
}
测试静态代理结果
public static void main(String[] args) {
//静态代理
TaoBao taoBao = new TaoBao(new KingUsbFactory());
System.out.println(taoBao.sell(2));
目标类执行了方法---
代理类执行了方法---
226.0
静态代理特点:
1.实现简单,易于理解。
2.目标类是固定的,要代理另一个目标类,必须重新写一个代理类,十分麻烦。
二、动态代理
1.JDK动态代理:通过Java的反射技术,在程序运行时生成一个目标接口的代理类实例对象,从而实现对目标类的调用和功能增强。
1)实现InvocationHandler接口
/**
* InvocationHandler类实现的invoke()内容,是代理类实现的业务逻辑:目标类方法+代理类的增强
*/
public class MyHandler implements InvocationHandler {
//目标类
Object target;
public MyHandler(Object target) {
this.target = target;
}
/*invoke(proxy,method,args)
proxy:代理对象,newProxyInstance方法的返回对象
method:调用的方法
args: 方法中的参数*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("执行目标类之前的增强++++++++++++++++++");
//调用目标类方法
float price = (float) method.invoke(target, args);
//实现功能增强
System.out.println("动态代理的功能增强++++++++++++++++++++++");
float n= price;
int x = (Integer) args[0];
price += x*25;
return price;
}
}
2)通过Proxy创建一个代理对象
//动态代理
//目标类
UsbProducer usbProducer = new KingUsbFactory();
InvocationHandler invocationHandler = new MyHandler(usbProducer);
//Proxy.newProxyInstance(a1,a2,a3)
//a1:要代理的接口的类加载器
//a2:目标类的接口
//a3:实现的invocationHandler
UsbProducer usbProducerAfter = (UsbProducer) Proxy.newProxyInstance(UsbProducer.class.getClassLoader(),
usbProducer.getClass().getInterfaces(),
invocationHandler);
float price = usbProducerAfter.sell(2);
System.out.println("最终价格为:"+price);
执行目标类之前的增强++++++++++++++++++
目标类执行了方法---
动态代理的功能增强++++++++++++++++++++++
最终价格为:226.0
JDK动态代理特点:
1)目标对象并不固定,而是活动的,可以由程序员传入。
2)程序员不需要手动编写代理类,而是通过java的反射技术动态生成,省去了很多麻烦。
3)通过Proxy生成的代理对象调用代理方法时,实际上是调用了InvocationHandler中的invoke()。
4)JDK动态代理要实现有一个前提:目标类必须实现了接口,因此,要对普通目标类进行动态代理,要用到CGLib。
2.CGLib动态代理
原理:java的继承机制。代理类继承目标类,并重写目标方法,当创建代理类对象并声明为目标类类型时,调用方法实现的是代理类的方法。