Java 代理模式
一、静态代理
1、通过继承实现代理
2、通过实现相同的接口进行代理
例:
接口
//统一接口 public interface Moveable { public void move(); }
被代理类
import java.util.Random; public class Car implements Moveable{ @Override public void move() { try { Thread.sleep(new Random().nextInt(1000)); System.out.println("汽车正在行驶中....."); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
代理类1
public class CarLogProxy implements Moveable { private Moveable m; public CarLogProxy(Moveable m) { super(); this.m = m; } @Override public void move() { System.out.println("日志开始。。。。。"); m.move(); System.out.println("日志结束。。。。。"); } }
代理类2
public class CarTimeProxy implements Moveable { private Moveable m; public CarTimeProxy(Moveable m) { super(); this.m = m; } @Override public void move() { long starttime = System.currentTimeMillis(); System.out.println("汽车开始行驶。。。。。"); m.move(); long endtime = System.currentTimeMillis(); System.out.println("汽车行驶结束。。。。。行驶时间("+(endtime - starttime)+")"); } }
客户端
public class Client { public static void main(String[] args) { Car car = new Car(); Moveable m = new CarTimeProxy(car); Moveable m1 = new CarLogProxy(m); m1.move(); } }
二、动态代理 (JDK动态代理)
Java动态代理类位于java.lang.reflect包下,一般主要涉及到以下两个类:
(1) Interface InvocationHandler:该类中仅定义了一个方法
public object invoke(Object obj, Method method, Object[] args)
第一个参数obj一般是指代理类,method是被代理的方法,
args为该方法的参数数组。这个抽象方法在代理类中动态实现。
(2) Proxy:该类即为动态代理类
static Object newProxyInstance(ClassLoader loader, Class[] interfaces,
InvocationHandler h):返回代理类的一个实例,返回后的代理类可以当作
被代理类使用(可使用被代理类的在接口中声明过的方法)
例:
接口
//统一接口 public interface Moveable { public void move(); }
被代理类
import java.util.Random; public class Car implements Moveable{ @Override public void move() { try { Thread.sleep(new Random().nextInt(1000)); System.out.println("汽车正在行驶中....."); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
动态代理handler
import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; public class TimeHandler implements InvocationHandler { public TimeHandler(Object target) { super(); this.target = target; } private Object target; /* * 参数: * proxy 被代理对象 * method 被代理对象的方法 * args 方法的参数 * * 返回值: * Object 方法的返回值 */ @Override public Object invoke(Object proxy, Method method, Object[] arg) throws Throwable { long starttime = System.currentTimeMillis(); System.out.println("汽车开始行驶。。。。。"); method.invoke(target); long endtime = System.currentTimeMillis(); System.out.println("汽车行驶结束。。。。。行驶时间("+(endtime - starttime)+")"); return null; } }
客户端代码
import java.lang.reflect.InvocationHandler; import java.lang.reflect.Proxy; public class Test { public static void main(String[] args) { Car car = new Car(); InvocationHandler h = new TimeHandler(car); Class<?> cls = car.getClass(); /** * loader 类加载器 * interfaces 实现接口 * h InvocationHandler */ Moveable m = (Moveable) Proxy.newProxyInstance(cls.getClassLoader(), cls.getInterfaces(), h); m.move(); } }
所谓Dynamic Proxy是这样一种class:
它是在运行时生成的class
该class需要实现一组interface
使用动态代理类时,必须实现InvocationHandler接口
步骤:
1、创建一个实现接口InvocationHandler的类,它必须实现invoke方法。
2、创建被代理的类以及接口
3、调用Proxy的静态方法,创建一个代理类
newProxyInstance(ClassLoader loader, Class[] interfaces, InvocationHandler h)
4、通过代理调用方法
CGLIB动态代理
1、导入cglib包
2、代理类实现 net.sf.cglib.proxy.MethodInterceptor接口
3、代理类实现 intercept(Object obj, Method m, Object[] args, MethodProxy proxy) 方法。
被代理类
public class Train { public void move() { System.out.println("火车行驶中......"); } }
代理类
import java.lang.reflect.Method; import net.sf.cglib.proxy.Enhancer; import net.sf.cglib.proxy.MethodInterceptor; import net.sf.cglib.proxy.MethodProxy; public class CglibProxy implements MethodInterceptor { private Enhancer enhancer = new Enhancer(); public Object getProxy(Class clazz) { //设置创建子类的类 enhancer.setSuperclass(clazz); enhancer.setCallback(this); return enhancer.create(); } /** * 拦截所有目标类方法的调用 * obj 目标类的实例 * m 目标方法的反射对象 * args 方法的参数 * proxy 代理类的实例 */ @Override public Object intercept(Object obj, Method m, Object[] args, MethodProxy proxy) throws Throwable { System.out.println("日志开始...."); //代理类调用父类的方法 proxy.invokeSuper(obj, args); System.out.println("日志结束...."); return null; } }
客户端
public class Client { public static void main(String[] args) { CglibProxy proxy = new CglibProxy(); Train t = (Train)proxy.getProxy(Train.class); t.move(); } }
JDK动态代理
1、只能代理实现了接口的类
2、没有实现接口的类不能实现JDK动态代理
CGLIB动态代理
1、针对类来实现代理的。
2、对指定目标产生一个子类,通过方法拦截技术拦截所有父类方法的调用。