JAVA笔记——代理模式
2016-04-01 15:18
501 查看
什么是代理
静态代理
JDK实现动态代理
cglib动态代理
而在编程中,代理类同样拥有被代理类部分功能,但是不仅如此,代理类可以在此基础之上附加一些自己的功能
代理类最常见的用法就是日志功能:在被代理类执行方法之前,写下日志。
现有一只鸟,它有一个fly方法,我们想在它fly的时候,写下日志
先写一个flyable接口:
写一个bird,实现接口
写一个日志代理类,注意,代理类也要实现同样的接口
测试:
结果:
静态代理的缺陷也很明显,它只能代理实现了相同接口的类。随着系统业务的增长,需要代理的类可能非常多,那我们也要写非常多的代理类
因此,我们需要动态代理
我们先写好一个flyable和bird
JDK的动态代理,我们需要实现接口InvocationHandler,例如我们写一个日志的动态代理
从上面代理类也可以看出,它不依赖于任何的类和接口
测试:
结果:
JDK的动态代理也有一定的缺陷,它要求被代理的类必须实现某个接口,也就是说,JDK的动态代理是根据接口来实现的
写一个bird类,有fly方法
代理类:实现MethodInterceptor接口。cglib创建的代理类事实上是被代理类的子类,使用Enhancer来创建
测试:
结果:
静态代理
JDK实现动态代理
cglib动态代理
什么是代理
举个生活中的例子:有时候我们想要买火车票,但是火车站太远,那么我们可以去附近的火车票代售点进行购买。此时,代售点就是代理,它拥有被代理对象的部分功能——售票功能。而在编程中,代理类同样拥有被代理类部分功能,但是不仅如此,代理类可以在此基础之上附加一些自己的功能
代理类最常见的用法就是日志功能:在被代理类执行方法之前,写下日志。
静态代理
需求:现有一只鸟,它有一个fly方法,我们想在它fly的时候,写下日志
先写一个flyable接口:
public interface Flyable { void fly(); }
写一个bird,实现接口
public class Bird implements Flyable { @Override public void fly() { System.out.println("bird is flying...."); } }
写一个日志代理类,注意,代理类也要实现同样的接口
public class LogProxy implements Flyable { private Flyable f; public LogProxy(Flyable f){ this.f = f; } @Override public void fly() { System.out.println("log is writing..."); f.fly(); System.out.println("over..."); } }
测试:
public static void main(String[] args) { Bird bird = new Bird(); Flyable f = new LogProxy(bird); f.fly(); }
结果:
静态代理的缺陷也很明显,它只能代理实现了相同接口的类。随着系统业务的增长,需要代理的类可能非常多,那我们也要写非常多的代理类
因此,我们需要动态代理
JDK实现动态代理
JDK为我们提供了动态代理的能力。动态代理的优势在于,它不依赖于任何接口或类我们先写好一个flyable和bird
public interface Flyable { void fly(); }
public class Bird implements Flyable { @Override public void fly() { System.out.println("bird is flying...."); } }
JDK的动态代理,我们需要实现接口InvocationHandler,例如我们写一个日志的动态代理
public class LogHandler implements InvocationHandler { private Object target; public LogHandler(Object target) { super(); this.target = target; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("log is writing..."); method.invoke(target, null); System.out.println("over..."); return null; } }
从上面代理类也可以看出,它不依赖于任何的类和接口
测试:
public class Test { public static void main(String[] args) { Bird bird = new Bird(); InvocationHandler h = new LogHandler(bird); Class<?> cls = bird.getClass(); ClassLoader loader = cls.getClassLoader(); Flyable f = (Flyable) Proxy.newProxyInstance(loader, cls.getInterfaces(), h); f.fly(); } }
结果:
JDK的动态代理也有一定的缺陷,它要求被代理的类必须实现某个接口,也就是说,JDK的动态代理是根据接口来实现的
cglib动态代理
除了JDK动态代理,我们也可以使用cglib来实现,二者的却别在于:cglib的动态代理是根据类来实现的,JDK的是根据接口来实现的写一个bird类,有fly方法
public class Bird { public void fly(){ System.out.println("bird is flying..."); } }
代理类:实现MethodInterceptor接口。cglib创建的代理类事实上是被代理类的子类,使用Enhancer来创建
public class LogProxy implements MethodInterceptor { private Enhancer enhancer = new Enhancer(); /** * 创建代理类 * @param cls * @return */ public Object getProxy(Class cls){ //设置父类 enhancer.setSuperclass(cls); 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("log ......."); //cglib创建的代理类其实是被代理类的子类,此处执行父类的方法,即执行被代理类真正要执行的方法 proxy.invokeSuper(obj, args); return null; } }
测试:
public class Test { public static void main(String[] args) { LogProxy proxy = new LogProxy(); Bird bird = (Bird) proxy.getProxy(Bird.class); bird.fly(); } }
结果:
相关文章推荐
- java对世界各个时区(TimeZone)的通用转换处理方法(转载)
- java-注解annotation
- java-模拟tomcat服务器
- java-用HttpURLConnection发送Http请求.
- java-WEB中的监听器Lisener
- Android IPC进程间通讯机制
- Android Native 绘图方法
- Android java 与 javascript互访(相互调用)的方法例子
- 介绍一款信息管理系统的开源框架---jeecg
- 聚类算法之kmeans算法java版本
- java实现 PageRank算法
- PropertyChangeListener简单理解
- c++11 + SDL2 + ffmpeg +OpenAL + java = Android播放器
- 插入排序
- 冒泡排序
- 堆排序
- 快速排序
- 二叉查找树