Java代理模式
2015-06-15 14:05
519 查看
代理模式的定义: 为其他对象提供一种代理以控制对这个对象的访问。代理对象起到中介作用,可以去掉功能服务或者添加额外的服务
静态代理: 代理和被代理对象在代理之前是确定的。他们都实现相同的接口或者继承相同的抽象类
UML图:
以聚合代理的方式实现静态代理为例:
首先抽象接口
被代理对象
代理类1:
代理类2:
测试:
运行结果:
但静态代理只能代理一种类型的被代理类,换个类型的就不行了,这需要动态代理
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) : 返回代理类的一个实例, 返回后的代理类可以当作被代理类使用
动态代理实现步骤
(1)创建一个实现接口InvocationHandler的类,它必须实现invoke方法
(2)创建被代理的类以及接口
(3)调用Proxy的静态方法,创建一个代理类
newProxyInstance(ClassLoader loader , Class[] interfaces , InvocationHandler h)
(4) 通过代理调用方法
例:
抽象接口
被代理类:
InvocationHandler 实现类
测试:
运行结果:
除了使用JDK实现动态代理之外,还可以使用CGLIB实现 ,需要引入cglib的jar包
被代理类:
代理类:
测试:
运行结果:
两种动态代理的区别
JDK动态代理:
(1) 只能代理实现了接口的类;
(2)没有实现接口的类不能实现JDK的动态代理。
CGLIB动态代理:
(1) 针对类来实现代理的;
(2)对指定目标类产生一个子类, 通过方法拦截技术拦截所有的父类方法的调用。
静态代理: 代理和被代理对象在代理之前是确定的。他们都实现相同的接口或者继承相同的抽象类
UML图:
以聚合代理的方式实现静态代理为例:
首先抽象接口
package proxy; public interface Moveable { void move(); }
被代理对象
package proxy; import java.util.Random; public class Car implements Moveable { public void move() { try { Thread.sleep(new Random().nextInt(1000)); System.out.println("汽车行驶....."); } catch (InterruptedException e) { e.printStackTrace(); } } }
代理类1:
package proxy; public class CarLogProxy implements Moveable { public CarLogProxy(Moveable m) { super(); this.m = m; } private Moveable m; public void move() { System.out.println("Log开始"); m.move(); System.out.println("Log结束"); } }
代理类2:
package proxy; public class CarTimeProxy implements Moveable { public CarTimeProxy(Moveable m) { super(); this.m = m; } private Moveable m; public void move() { System.out.println("计时开始"); m.move(); System.out.println("计时结束"); } }
测试:
package proxy; public class Client { public static void main(String[] args) { Car car = new Car(); CarLogProxy clp = new CarLogProxy(car); CarTimeProxy ctp = new CarTimeProxy(clp); ctp.move(); } }
运行结果:
计时开始 Log开始 汽车行驶..... Log结束 计时结束
但静态代理只能代理一种类型的被代理类,换个类型的就不行了,这需要动态代理
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) : 返回代理类的一个实例, 返回后的代理类可以当作被代理类使用
动态代理实现步骤
(1)创建一个实现接口InvocationHandler的类,它必须实现invoke方法
(2)创建被代理的类以及接口
(3)调用Proxy的静态方法,创建一个代理类
newProxyInstance(ClassLoader loader , Class[] interfaces , InvocationHandler h)
(4) 通过代理调用方法
例:
抽象接口
package proxy; public interface Moveable { void move(); }
被代理类:
package proxy; import java.util.Random; public class Car implements Moveable { public void move() { try { Thread.sleep(new Random().nextInt(1000)); System.out.println("汽车行驶...."); } catch (InterruptedException e) { e.printStackTrace(); } } }
InvocationHandler 实现类
package proxy; 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; public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("计时前"); method.invoke(target); System.out.println("计时后"); return null; } }
测试:
package proxy; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Proxy; import proxy.Car; import proxy.Moveable; public class Test { public static void main(String[] args) { Car car = new Car(); InvocationHandler h = new TimeHandler(car); Class<?> cls = car.getClass(); Moveable m = (Moveable)Proxy.newProxyInstance(cls.getClassLoader(), cls.getInterfaces(), h); m.move(); } }
运行结果:
计时前 汽车行驶.... 计时后
除了使用JDK实现动态代理之外,还可以使用CGLIB实现 ,需要引入cglib的jar包
被代理类:
package cglibproxy; public class Train { public void move(){ System.out.println("汽车行驶..."); } }
代理类:
package cglibproxy; 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(); } 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; } }
测试:
package cglibproxy; public class Client { /** * @param args */ 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)对指定目标类产生一个子类, 通过方法拦截技术拦截所有的父类方法的调用。
相关文章推荐
- JAVA设计模式之单例模式
- ubuntu12.04 安装配置jdk1.7
- Java多线程理解
- Java设计模式 —— 适配器(Adapter)
- JAVA集合小结
- Java NIO系列教程(六) Selector
- Spring用@Scheduled 定时任务
- Java设计模式 —— 组合(Composite)
- POI操作Excel常用方法总结
- Java设计模式 —— 策略(Strategy)
- Eclipse 插件: JSEclipse
- Spring-boot & spring.security
- MyEclipse移动Web模拟器指南(一)
- JAVA实现的一个简单的Socket Server范例
- Java资源库正式上线啦
- 疯狂Java学习笔记(83)----------继承详解
- spring-boot rest 加jsp页面
- 从Java视角理解CPU上下文切换(Context Switch)
- LDAP用户验证(Spring-LDAP)
- 使用Spring Boot快速构建应用