使用代理模式的作用:
功能增强:在你原有的功能上,增加了额外的功能。
控制访问:代理类不让你访问目标。例如商家不让用户访问厂家
实现代理的方式
静态代理:代理类是自己手工实现的,
自己创建一个java类表示代理类,同时所要的代理目标是确定的。
特点:实现简单;容易理解
缺点:目标类增加,代理类可能也要成倍增加;当接口中功能修改/增加,会影响众多实现类
动态代理:可以避免静态代理的缺点
在程序的执行过程中,使用jdk的反射机制,创建代理类对象,并动态指定要代理的目标类
也就是使用jdk的反射机制,创建对象的能力,创建的是代理类的对象,而不用手动创建
类文件。
什么是动态代理?
使用jdk反射机制机制,创建对象的能力。创建的是代理类的对象,而不用你创建类文件,不用写java文件。
jdk动态代理必须有接口,目标类必须实现接口;
没有接口时,可以用cglib
动态代理能做什么?
可以在不改变原来目标方法功能的前提下,可以在代理中增强自己的功能代码。
例如A写了一个方法,B想去实现该方法的时候,发现该方法不完善,想要自己增强该方法,但是又不能访问其原码。于是可以用到动态代理,为该方法增强功能,既保证了原方法的完整,又不会修改其代码,符合了OCP开闭原则。
JDK动态代理的实现:
InvocationHandler接口:(执行的功能能代码)
只有一个方法:invoke()表示代理对象要执行的功能代码(代理类要完成的功能写在该方法中)
代理类完成的功能:用目标方法;功能增强
怎么用:创建类实现接口InvocationHandler。
重写invoke()方法,把原来静态代理中代理类要完成的功能写在方法中。
Method类:(执行的目标方法)
表示方法的,就是目标类中的方法
作用:通过Method可以执行某个目标类的方法,Method.invoke();
怎么用:method.invoke(目标对象,“方法参数”);
Proxy类:(创建对象)
核心的对象,创建代理对象。
使用Proxy类的方法,代替new的使用。
方法:静态方法 newProxyInstance()
作用:创建代理类对象。
public static Object new ProxyInstance(ClassLoader loader,Class>[] interfaces,InvocationHandler h)
参数:
1.ClassLoader loader:类加载器,负责向内存中加载对象,使用反射机制获取对象的ClassLoader
类A,A.getClass(),getCloassLoader(),目标对象的类加载器
2.Class>[] interfaces:接口,目标对象实现的接口,也是反射获取的。
3.InvocationHandler h:我们自己写的,代理类要完成的功能
代码实例:
package service;
public interface UsbSell {
float sell(int amount);
}
接口实现类:
package factory;
import service.UsbSell;
//目标类
public class UsbKingFactory implements UsbSell {
@Override
public float sell(int amount) {
//目标方法
System.out.println("目标类中,执行sell目标方法");
return 85.0f;
}
}
InvocationHandler接口的实现类:
package handler;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
//必须实现InvocationHandler接口,完成代理类要做的功能
//1.调用目标方法 2.功能增强
public class MySellHandler implements InvocationHandler {
Object target=null;
//动态代理的目标对象
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=price+25;
res=price;
}
return res;
}
}
测试方法:
import factory.UsbKingFactory;
import handler.MySellHandler;
import service.UsbSell;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.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(1);
System.out.println("通过动态代理对象,调用方法:"+price);
}
}