Java代理模式
来源:互联网 发布:域名加空间多少钱 编辑:程序博客网 时间:2024/06/05 06:57
Java代理模式
定义:
代理模式是常用的java设计模式,他的特征是代理类与委托类有同样的接口,代理类主要负责为委托类预处理消息、过滤消息、把消息转发给委托类,以及事后处理消息等。代理类与委托类之间通常会存在关联关系,一个代理类的对象与一个委托类的对象关联,代理类的对象本身并不真正实现服务,而是通过调用委托类的对象的相关方法,来提供特定的服务。
代理分为静态代理和动态代理两种:
静态代理:由程序员创建或特定工具自动生成源代码,再对其编译。在程序运行前,代理类的.class文件就已经存在了
动态代理:在程序运行时,运用反射机制动态创建而成
静态代理样例
用户接口类:
package com.statics.proxy;public interface UserDAO{ //用户登录接口 public void login();}
用户实现类:
package com.statics.proxy;public class UserImpl implements UserDAO{ //用户登录操作 @Override public void login() { System.out.println("user login!"); }}
用户代理类:
package com.statics.proxy;public class UserProxy implements UserDAO{ private UserImpl userImpl; public UserProxy(UserImpl userImpl) { super(); this.userImpl = userImpl; } @Override public void login() { //在委托类方法执行前调用相应逻辑代码 System.out.println("check username"); userImpl.login(); //在委托类方法执行前调用相应逻辑代码 System.out.println("user login result"); }}
代理测试类:
package com.statics.proxy;public class Test{ public static void main(String[] args) { UserProxy proxy =new UserProxy(new UserImpl()); proxy.login(); }}
输出结果:
check username
user login!
user login result
从上面的代码中可以看出,委托类UserImpl执行login方法,其实是通过代理类UserProxy调用UserImpl类的login方法。代理类本身并没有委托类的逻辑方法,只是通过调用委托类的方法,并且在执行委托类的方法前后调用一定的业务逻辑。
静态代理虽然实现了委托类的业务逻辑,但是每一个委托类必须对应一个代理类,当委托类很多的况下,代理类也会变得很多。而且代理方法除了调用的方法不一样,其他的业务逻辑都一样,这样就代码的重用率会变得很低,同时也不利于维护。因而我们引进动态代理。
动态代理
动态代理的实现方法可以分为4种:
JDK反射机制实现
CGLIB
- Javassist
- asm
JDK反射机制实现动态代理
UserDAO 接口类:
package com.dynamic.proxy;public interface UserDao{ //唱歌的工作 public void sing(); //跳舞操作 public void dance()}
UserImpl 实现类:
package com.dynamic.proxy;public class UserImp implements UserDao{ //唱歌方法实现 @Override public void sing() { System.out.println("sing a song.."); } //跳舞方法实现 @Override public void dance() { System.out.println("begin dance!"); }}
JDK动态代理类:
package com.dynamic.proxy;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;public class UserProxyHandler implements InvocationHandler{ //传入委托类对象(被代理对象) private Object realObject; public UserProxyHandler(Object realObject) { super(); this.realObject = realObject; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { //proxy 代理类 并非委托类 //记录日志 System.out.println("log/-"+method.getName()+"- begin run"); //激活被代理类的方法 Object result = method.invoke(realObject, args); //记录日志 System.out.println("log/-"+method.getName()+"- end of run"); return result; }}
测试方法:
package com.dynamic.proxy;import java.lang.reflect.Proxy;public class Test{ public static void main(String[] args) { UserImp userImp = new UserImp(); UserProxyHandler userProxyHandler = new UserProxyHandler(userImp); //生成代理类 UserDao userProxy = (UserDao)Proxy.newProxyInstance(UserDao.class.getClassLoader(),new Class[]{UserDao.class}, userProxyHandler); userProxy.sing(); userProxy.dance(); }}
输入结果:
log/-method:sing- begin run
sing a song..
log/-method:sing- end of run
log/-method:dance- begin run
begin dance!
log/-method:dance- end of run
上面代码中,给每个被代理类的方法执行前后加入日志记录功能。动态代理与静态代理最大的区别就是,动态代理类的字节码在程序运行的过程时由Java的反射机制动态生成,无需程序员重新编码。动态代理不仅简化了编程工作,而且提高了程序的扩展性,因为通过Java的反射机制可以生成任何类的动态代理类。
但是JDK动态代理需要依靠接口实现,如果被代理类没有接口的话,则动态代理无法实现。cglib方法很好的解决了这个问题。
CGLIB动态代理
UserImpl实现类:
package com.cglib.dynamic.proxy;public class UserImp { // public void sing() { System.out.println("sing a song.."); } public void dance() { System.out.println("begin dance.."); }}
cglib代理类:
package com.cglib.dynamic.proxy;import java.lang.reflect.Method;import net.sf.cglib.proxy.MethodInterceptor;import net.sf.cglib.proxy.MethodProxy;/*实现方法拦截器接口*/public class UserCglibProxy implements MethodInterceptor{ @Override public Object intercept(Object object, Method method, Object[] arg2, MethodProxy methodProxy) throws Throwable { System.out.println("log:method-" + method.getName() + "- begin runing"); System.out.println(method.getName()); System.out.println(methodProxy.getSuperName()); Object result = methodProxy.invokeSuper(object, arg2); return result; }}
测试类:
package com.cglib.dynamic.proxy;import net.sf.cglib.proxy.Enhancer;public class Test{ public static void main(String[] args) { Enhancer enhancer =new Enhancer(); //设置要创建的动态代理的类 enhancer.setSuperclass(UserImp.class); //设置回调 enhancer.setCallback(new UserCglibProxy()); UserImp userImp =(UserImp) enhancer.create(); userImp.sing(); userImp.dance(); }}
输出结果:
log:method-sing- begin runing
sing
CGLIBsing 0
sing a song..
log:method-dance- begin runing
dance
CGLIBdance 1
begin dance..
- Java代理之代理模式
- java代理模式---静态代理
- java代理模式--动态代理
- 代理模式&java动态代理
- JAVA代理模式--静态代理
- JAVA代理模式--动态代理
- JAVA动态代理 代理模式
- Java代理模式-静态代理
- java代理模式-动态代理
- Java代理模式 静态代理 动态代理
- JAVA代理模式与动态代理模式
- JAVA代理模式与动态代理模式
- JAVA代理模式与动态代理模式
- JAVA代理模式与动态代理模式
- JAVA代理模式与动态代理模式
- JAVA代理模式与动态代理模式
- Java代理模式和kotlin代理模式
- Java中的代理模式
- TQ210 —— NandFlash
- 什么是二叉树
- 统计int数组中重复数字的个数
- FreeMarker Servlet 的配置 (web.xml)
- Android系统ANR以及Force Close出现的原因以及解决办法
- Java代理模式
- 多线程编程之NSOperationQueue
- struct匿名字段和interface,断言
- 线程总结
- FreeMarker在Web应用中的配置
- C++14新特性总结
- jQuery中Ajax事件请求状态
- 支付宝支付失败:4000
- JVM内存模型和关键参数设置