package com.proxy; import java.util.Random; /** * Created by 79782 on 2018/6/30. */ public class Car implements MoveAble { @Override public void move() { try { Thread.sleep(new Random().nextInt(1000)); System.out.println("汽车行驶中..."); } catch (InterruptedException e) { e.printStackTrace(); } } }
package com.proxy; /** * Created by 79782 on 2018/6/30. */ public class Car2 extends Car { public void move(){ long starttime=System.currentTimeMillis(); System.out.println("汽车开始行驶..."); super.move(); long endtime=System.currentTimeMillis(); System.out.println("汽车结束行驶... 汽车行驶时间:" + (endtime - starttime) + "ms"); } }
package com.proxy; /** * Created by 79782 on 2018/6/30. */ public class Car3 implements MoveAble { private Car car; public Car3(Car car) { super(); this.car = car; } @Override public void move() { long starttime=System.currentTimeMillis(); System.out.println("汽车开始行驶..."); car.move(); long endtime=System.currentTimeMillis(); System.out.println("汽车结束行驶... 汽车行驶时间:" + (endtime - starttime) + "ms"); } }
package com.proxy; /** * Created by 79782 on 2018/6/30. */ public class Client { public static void main(String[] args) { /* Car car=new Car(); car.move();*/ /**使用集成方法 * MoveAble moveAble=new Car2(); moveAble.move();*/ //使用聚合方式实现 Car car=new Car(); MoveAble moveAble=new Car3(car); moveAble.move(); } }
package com.proxy; /** * Created by 79782 on 2018/6/30. */ public interface MoveAble { public void move(); }
使用聚合的方式实现代理的好处是多态
实现功能的叠加:
package com.proxy; import java.util.Random; /** * Created by 79782 on 2018/6/30. */ public class Car implements MoveAble { @Override public void move() { try { Thread.sleep(new Random().nextInt(1000)); System.out.println("汽车行驶中..."); } catch (InterruptedException e) { e.printStackTrace(); } } }
package com.proxy; /** * Created by 79782 on 2018/6/30. */ public class CarLogProxy implements MoveAble { /** * 因为代理类和被代理类都是实现了相同的接口,所以构造方法传递的参数可以是MoveAble对象 */ private MoveAble moveAble; public CarLogProxy(MoveAble moveAble) { super(); this.moveAble=moveAble; } @Override public void move() { long starttime=System.currentTimeMillis(); System.out.println("日志开始..."); moveAble.move(); long endtime=System.currentTimeMillis(); System.out.println("日志结束:" + (endtime - starttime) + "ms"); } }
package com.proxy; /** * Created by 79782 on 2018/6/30. */ public class CarTimeProxy implements MoveAble { /** * 因为代理类和被代理类都是实现了相同的接口,所以构造方法传递的参数可以是MoveAble对象 */ private MoveAble moveAble; public CarTimeProxy(MoveAble moveAble) { super(); this.moveAble=moveAble; } @Override public void move() { long starttime=System.currentTimeMillis(); System.out.println("汽车开始行驶..."); moveAble.move(); long endtime=System.currentTimeMillis(); System.out.println("汽车结束行驶... 汽车行驶时间:" + (endtime - starttime) + "ms"); } }
package com.proxy; /** * Created by 79782 on 2018/6/30. */ public class Client { public static void main(String[] args) { Car car=new Car(); CarTimeProxy ctp=new CarTimeProxy(car); CarLogProxy clp=new CarLogProxy(ctp); clp.move(); } }
package com.proxy; /** * Created by 79782 on 2018/6/30. */ public interface MoveAble { public void move(); }
时间代理和日志代理都是实现相同的接口,如果不同的类需要这些时间代理和日志代理,如何将他们统一,用一个TimeProxy实现对小汽车,自行车的动态代理,如下:
JDK动态代理
package com.jdkproxy; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; /** * Created by 79782 on 2018/6/30. */ public class LogHandler implements InvocationHandler { private Object target; public LogHandler(Object target) { this.target = target; } /** * * @param proxy 被代理的对象 * @param method 被代理动向的方法 * @param args 方法的参数 * @return Object * @throws Throwable */ @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { long starttime=System.currentTimeMillis(); System.out.println("日志开始记录..."); method.invoke(target); long endtime=System.currentTimeMillis(); System.out.println("日志记录结束,时间:" + (endtime - starttime) + "ms"); return null; } }
package com.jdkproxy; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; /** * Created by 79782 on 2018/6/30. */ public class TimeHandler implements InvocationHandler { private Object target; public TimeHandler(Object target) { this.target = target; } /** * * @param proxy 被代理的对象 * @param method 被代理动向的方法 * @param args 方法的参数 * @return Object * @throws Throwable */ @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { long starttime=System.currentTimeMillis(); System.out.println("汽车开始行驶..."); method.invoke(target); long endtime=System.currentTimeMillis(); System.out.println("汽车结束行驶... 汽车行驶时间:" + (endtime - starttime) + "ms"); return null; } }
package com.jdkproxy; import com.proxy.Car; import com.proxy.MoveAble; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Proxy; /** * Created by 79782 on 2018/6/30. */ public class Test { public static void main(String[] args) { Car car=new Car(); InvocationHandler timeHandler=new TimeHandler(car); /** * loader:类加载器 * interfaces:实现接口 * h InvocationHandler */ Class<?> cls=car.getClass(); MoveAble moveAble=(MoveAble)Proxy.newProxyInstance(cls.getClassLoader(), cls.getInterfaces(), timeHandler); InvocationHandler logHandelr=new LogHandler(moveAble); MoveAble m2=(MoveAble)Proxy.newProxyInstance(cls.getClassLoader(), cls.getInterfaces(), logHandelr); m2.move(); } }
JDK动态代理:
1.只能代理实现了接口的类。
2.没有实现接口的类不能实现JDK的动态代理。
Cglib动态代理:
1.针对类来实现代理。
2.对指定目标类产生一个子类,通过方法拦截技术拦截所有父类方法的调用。
3.因为是使用继承的方式,所以不能对final修饰的类进行代理。
使用Cglib实现动态代理:
<dependency> <groupId>cglib</groupId> <artifactId>cglib</artifactId> <version>3.2.3</version> </dependency>
package com.cglibproxy; import net.sf.cglib.proxy.Enhancer; import net.sf.cglib.proxy.MethodInterceptor; import net.sf.cglib.proxy.MethodProxy; import java.lang.reflect.Method; /** * Created by 79782 on 2018/6/30. */ public class CglibProxy implements MethodInterceptor { private Enhancer enhancer=new Enhancer(); public Object getProxy(Class clzz){ //设置创建子类的类 enhancer.setSuperclass(clzz); enhancer.setCallback(this); return enhancer.create(); } /** * 拦截所有目标类方法的调用 * @param o 目标类的实例 * @param method 目标方法的反射对象 * @param objects 方法的参数 * @param methodProxy 代理类的实例 * @return * @throws Throwable */ @Override public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable { System.out.println("日志开始..."); //代理类调用父类的方法 methodProxy.invokeSuper(o,objects); System.out.println("日志结束..."); return null; } }
package com.cglibproxy; /** * Created by 79782 on 2018/6/30. */ public class Train { public void move(){ System.out.println("火车行驶中..."); } }
package com.cglibproxy; /** * Created by 79782 on 2018/6/30. */ public class Client { public static void main(String[] args) { CglibProxy proxy=new CglibProxy(); Train t=(Train)proxy.getProxy(Train.class); t.move(); } }
JDK动态代理可以对实现某一接口的任意类,任意方法产生任意的代理。
动态代理实现思路:通过Proxy的newProxyInstance返回代理对象
动态代理实现思路:
1.声明一段源码(动态产生代理)
2.编译源码,产生新的类(代理类)
3.将这个类load到内存中,产生一个新的对象(代理对象)
4.return代理对象