淄博网站建设招聘,如何建设网站效果好,wordpress 修改 注册,淘宝自动推广软件设计模式--结构型--代理模式 代理模式概述结构静态代理案例#xff1a;卖车票jdk动态代理cglib代理三种代理对比优缺点使用场景 代理模式
概述
由于某些原因需要给某对象提供一个代理以控制该对象的访问。这时#xff0c;访问对象不适合或者不能直接引用目标对象#xff0… 设计模式--结构型--代理模式 代理模式概述结构静态代理案例卖车票jdk动态代理cglib代理三种代理对比优缺点使用场景 代理模式
概述
由于某些原因需要给某对象提供一个代理以控制该对象的访问。这时访问对象不适合或者不能直接引用目标对象代理对象作为访问对象和目标对象之间的中介。 java中的代理机制分为静态代理和动态代理
静态代理代理类在在编译期就生成动态代理代理类在java运行时动态生成。 JDK代理CGLib代理
结构
代理模式分为三种角色
抽象主题类通过接口或抽象类声明真实主题和代理对象实现的业务方法。真实主题类实现了抽象主题中的具体业务是代理对象所代表的真实对象是最终要引用的对象。代理类提供了与真实主题相同的接口其内部含有对真实主题的引用它可以访问、控制或扩展真实主题的功能。
静态代理案例卖车票
市面上任何卖火车票软件都是通过12306来买的这就是一个典型的代理模式12306是目标对象其他售票软件是代理对象。
public class ProxyPoint implements SellTicket{// 声明12306类对象private TrainStation trainStation new TrainStation();Overridepublic void sell() {System.out.println(其它app买票---可以增强);trainStation.sell();}
}/*** 卖火车票的接口*/
public interface SellTicket {void sell();
}public class TrainStation implements SellTicket{Overridepublic void sell() {System.out.println(12306卖火车票);}
}public class Test01 {public static void main(String[] args) {ProxyPoint proxyPoint new ProxyPoint();proxyPoint.sell();}
}从上面代码中可以看出测试类是直接访问ProxyPoint类对象也就是说ProxyPoint作为目标访问对象和目标对象的中介同时也对sell方法进行了增强。
jdk动态代理
接下来使用动态代理实现上面案例java中提供了一个动态代理类ProxyProxy并不是我们上面说的代理对象类 而是提供了一个创建代理对象的静态方法newProxyInstance来获取代理对象。
/*** 获取代理对象的工厂类* 代理类也实现了对应的接口*/
public class ProxyFactory {// 声明目标对象private TrainStation station new TrainStation();public SellTicket getProxyObject(){/*** ClassLoader loader 类加载器用于加载代理类。可以通过目标对象获取类加载器* Class?[] interfaces 代理类实现的接口的字节码对象* InvocationHandler h 代理对象的调用处理程序*/SellTicket proxyObject (SellTicket) Proxy.newProxyInstance(station.getClass().getClassLoader(),station.getClass().getInterfaces(),/*** Object proxy代理对象和proxyObject对象是同一个对象* Method method对接口中的方法进行封装的method对象* Object[] args调用方法的实际参数* 返回值方法的返回值*/new InvocationHandler() {Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {//System.out.println(代售app---增强);// 执行目标对象的方法return method.invoke(station, args);}});return proxyObject;}
}/*** 卖火车票的接口*/
public interface SellTicket {void sell();
}cglib代理
/*** 代理对象工厂,用来获取代理对象*/
public class ProxyFactory implements MethodInterceptor {private TrainStation station new TrainStation();public TrainStation getProxyObject(){// 创建Enhancer对象,类似jdk代理中的Proxy类Enhancer enhancer new Enhancer();// 设置父类的字节码对象enhancer.setSuperclass(TrainStation.class);// 设置回调函数enhancer.setCallback(this);// 创建代理对象TrainStation proxyObject (TrainStation) enhancer.create();return proxyObject;}Overridepublic Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {System.out.println(cglib代理);// 要调用目标对象的方法TrainStation invoke (TrainStation) method.invoke(station, objects);return invoke;}
}public class TrainStation {public void sell() {System.out.println(12306卖火车票);}
}public class Test02 {public static void main(String[] args) {// 创建代理工厂对象ProxyFactory factory new ProxyFactory();// 获取代理对象TrainStation proxyObject factory.getProxyObject();// 调用代理对象中的sell方法proxyObject.sell();}
}三种代理对比
jdk代理和cglib代理 使用CGLib实现动态代理cglib底层采用ASM字节码生产框架使用字节码技术生成代理类在jdk1.6之前比使用java反射效率要高。 唯一需要注意的是cglib不能对声明为final的类或方法进行代理因为cglib原理是动态生成被代理的子类。 在jdk1.8对jdk动态代理优化后jdk代理效率高于cglib代理如果有接口使用jdk代理没有接口使用cglib代理。 动态代理和静态代理 动态代理与静态代理相比较最大的好处是接口中声明的所有方法都被转移到调用处理器一个集中的方法处理InvocationHandler.invoke。这样在接口 方法数量比较多的时候我们可以灵活处理而不需要像静态代理那样每一个方法进行中转。 如果接口增加一个方法静态代理模式处理实现所有类需要实现这个方法外所有代理类也需要实现此方法。增加了代码维护的复杂度。而动态代理不会出现该问题
优缺点
优点 代理模式在客户端与目标对象之间起到了一个中介作用和保护作用代理对象可以扩展目标对象的功能代理模式能将客户端与目标对象分离在一定程度上降低了系统的耦合度 缺点 增加了系统的复杂度
使用场景
远程代理 本地服务通过网络请求远程服务。为了实现本地到远程的通信我们需要实现网络通信处理其中可能的异常。为良好的代码设计和可维护性 我们将网络通信部分隐藏起来只暴露给本地服务一个接口通过该接口即可访问远程服务提供的功能而不必过多关心通信部分的细节。 防火墙代理 将浏览器配置成使用代理功能时防火墙就可以将浏览器的请求转给互联网当互联网返回响应时代理服务器再把他转给你的浏览器。 保护代理 控制对一个对象的访问如果需要可以给不同的用户提供不同级别的使用权限。