Java代理模式
Posted nox-np
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java代理模式相关的知识,希望对你有一定的参考价值。
代理模式学习
- 基本概念
- 具体实现方式
一基本概念
为其他对象提供一种代理,以控制对这个对象的访问。代理对象起到中介作用,可去掉功能服务或增加额外的服务。
二实现方式
- 静态代理
- 动态代理
1、静态代理
静态代理实现方式有:继承和实现接口两种方式,通常会选用后者。
1 package cn.np.proxy.staticproxy; 2 3 /** 4 * @author np 5 * @date 2018/9/9 6 * 目标对象实现接口 7 */ 8 public interface TicketHandler { 9 void saleTicket(); 10 }
1 package cn.np.proxy.staticproxy; 2 3 /** 4 * @author np 5 * @date 2018/9/9 6 * 目标对象实现类 7 */ 8 public class TrainStation implements TicketHandler{ 9 10 @Override 11 public void saleTicket() { 12 System.out.println("销售火车票-出票来自火车站"); 13 } 14 }
1 package cn.np.proxy.staticproxy; 2 3 /** 4 * @author np 5 * @date 2018/9/9 6 * 静态代理类 7 */ 8 public class TicketProxy implements TicketHandler{ 9 10 private TrainStation trainStation; 11 12 public TicketProxy(){ 13 14 } 15 16 public TicketProxy(TrainStation trainStation){ 17 this.trainStation=trainStation; 18 } 19 20 @Override 21 public void saleTicket() { 22 System.out.println("出票前-代理类"); 23 if(null!=trainStation){ 24 trainStation.saleTicket(); 25 } 26 System.out.println("出票后-代理类"); 27 } 28 }
1 package cn.np.proxy.staticproxy; 2 3 /** 4 * @author np 5 * @date 2018/9/9 6 * 7 * 静态代理测试 8 */ 9 public class Client { 10 11 public static void main(String[] args){ 12 TrainStation trainStation=new TrainStation(); 13 trainStation.saleTicket(); 14 15 TicketProxy ticketProxy=new TicketProxy(trainStation); 16 ticketProxy.saleTicket(); 17 } 18 }
输出结果:
销售火车票-出票来自火车站 出票前-代理类 销售火车票-出票来自火车站 出票后-代理类
总结:
优点:不对对象进行修改的前提下,对目标对象进行扩展和拦截;
缺点:因为代理对象需要实现与目标对象一样的接口,会导致代理类维护复杂,同一逻辑的代理类需要实现不同类型的目标对象的接口,如以上例子中需要代理销售飞机票、汽车票等。
2、动态代理
动态在内存中得到目标对象的实例,执行目标方法。实现方式有两种:JDK动态代理和Cglib动态代理,JDK动态代理只能代理实现类接口的类;cglib动态代理是针对类来实现的(继承)。
JDK动态代理实现的步骤:
- 动态代理类实现接口java.lang.reflect.InvocationHandler
- 创建被代理的类及接口
- 调用Proxy.newProxyInstance(ClassLoader loader, Class<?>[] interfaces,InvocationHandler h),动态创建代理类
package cn.np.proxy.dynamic; /** * @author np * @date 2018/9/9 */ public interface TicketHandler { void saleTicket(); } public interface LogHandler { void writeLog(); }
1 package cn.np.proxy.dynamic; 2 3 import java.lang.reflect.InvocationHandler; 4 import java.lang.reflect.Method; 5 6 /** 7 * @author np 8 * @date 2018/9/9 9 * 动态代理类 10 */ 11 public class TicketDynamicProxy implements InvocationHandler { 12 13 private Object target; 14 15 public TicketDynamicProxy(Object object){ 16 target=object; 17 } 18 19 /** 20 * @param proxy 被代理对象 21 * @param method 被代理对象方法 22 * @param args 被代理对象方法参数 23 * @return 24 * @throws Throwable 25 */ 26 @Override 27 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { 28 System.out.println("动态代理-执行目标方法前"); 29 Object result=method.invoke(target); 30 System.out.println("动态代理-执行目标方法后"); 31 return result; 32 } 33 }
1 package cn.np.proxy.dynamic; 2 3 4 import java.util.Date; 5 6 /** 7 * @author np 8 * @date 2018/9/9 9 */ 10 public class TrainStation implements TicketHandler,LogHandler{ 11 12 @Override 13 public void saleTicket() { 14 System.out.println("销售火车票-出票来自火车站"); 15 } 16 17 @Override 18 public void writeLog() { 19 System.out.println("记录日志,当前时间是:"+new Date().getTime()); 20 } 21 }
1 package cn.np.proxy.dynamic; 2 3 import java.lang.reflect.InvocationHandler; 4 import java.lang.reflect.Proxy; 5 6 /** 7 * @author np 8 * @date 2018/9/9 9 */ 10 public class Client { 11 12 public static void main(String[] agrs){ 13 TrainStation trainStation=new TrainStation(); 14 Class<?> clz=trainStation.getClass(); 15 Class<?>[] interfaces=clz.getInterfaces(); 16 17 InvocationHandler handler=new TicketDynamicProxy(trainStation); 18 19 TicketHandler ticketHandler=(TicketHandler) Proxy.newProxyInstance(clz.getClassLoader(),interfaces,handler); 20 ticketHandler.saleTicket(); 21 22 LogHandler logHandler=(LogHandler) Proxy.newProxyInstance(clz.getClassLoader(),interfaces,handler); 23 logHandler.writeLog(); 24 25 } 26 }
输出结果:
动态代理-执行目标方法前 销售火车票-出票来自火车站 动态代理-执行目标方法后 动态代理-执行目标方法前 记录日志,当前时间是:1536478014151 动态代理-执行目标方法后
优点:代理类不需要和目标类实现同一个接口,增加了灵活性
缺点:代理对象不需要实现接口,但是目标对象一定要实现接口,否则无法使用JDK动态代理。
以上是关于Java代理模式的主要内容,如果未能解决你的问题,请参考以下文章