网站首页 > java教程 正文
代理模式使用代理对象完成用户的请求,屏蔽用户对真实对象的访问。
代理模式的用途很多,比如因为安全原因,需要屏蔽客户端直接访问真实对象;或者在远程调用中,需要使用代理对象处理远程方法中的技术细节;或者为了提升系统,对真是对象进行封装,从而达到延迟加载的目的。
在系统启动时,将消耗资源最多的方法使用代理模式分离,就可以加快系统的启动速度,减少用户的等待时间。在用户真正在做查询是,再由代理类加载真实的类,完成用户请求。这就是使用代理模式达到延迟加载的目的。
1.静态代理实现:
主题接口:
public interface IDBQuery { String request(); }
真实主题:
public class DBQuery implements IDBQuery { public DBQuery(){ try { Thread.sleep(10000); } catch (Exception e) { e.printStackTrace(); } } public String request() { return "string request"; } }
代理类:
public class IDBQueryProxy implements IDBQuery { private DBQuery dbquery; public String request() { if(dbquery==null) dbquery = new DBQuery(); return dbquery.request(); } }
最后,主函数:
public class ProxyText { public static void main(String[] args) { IDBQuery dbquery = new IDBQueryProxy(); System.out.println(dbquery.request()); } }
静态代理注意,代理类是真实类实现共同的接口,并且代理类引用真实类对象,将耗时操作放在代理类方法中实现。
动态代理:
动态代理即运行时,动态生成代理类。即:代理类的字节码在运行时生成并载入当前的classloader。与静态代理相比,动态代理不需要为真实注意封装一个形式上完全一样的封装类,假如主题接口很多,就要为每一个接口写一个代理方法是很烦人的,如果接口有变动,真实类和代理类都需要变化,这样不利于系统维护;其次,使用一些动态代理的生成方法甚至可以在运行是指定代理类的执行逻辑,从而大大提高的系统的灵活性。
主题接口:
public interface IDBQuery { String request(); }
jdk代理类:
public class JdbDbqueryHandler implements InvocationHandler{ IDBQuery idbquery = null; @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { if(idbquery==null){ idbquery = new DBQuery(); } return idbquery.request(); } public static IDBQuery createJdbProxy(){ IDBQuery jdkProxy = (IDBQuery) Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(), new Class[]{IDBQuery.class}, new JdbDbqueryHandler()); System.out.println("JdbDbqueryHandler.createJdbProxy()"); return jdkProxy; } }
主函数:
public class ProxyText { public static void main(String[] args) { IDBQuery idbQuery = JdbDbqueryHandler.createJdbProxy(); System.out.println(idbQuery.request()); } }
另外,也可以使用CGLIB和javassist动态代理与jdk动态代理类似,但是jdk动态类的创建过程最快,因为这个内置实现的difineclass()方法被定义为native实现,故性能优于其他。在代理类的函数调用上,JDK的动态代理不如CGLIB和javassist动态代理,而javassist动态代理性能质量最差,甚至不如JDK的实现。在实际开发应用中,代理类的方法调用频率要远远高于代理类的实际生成频率,故动态代理的方法调用性能应该成为性能的关注点。JDK动态代理强制要求代理类和真是主题实现统一接口,CGLIB和javassist动态代理没有这样的要求。
在java中,动态代理的实现涉及到classloader的使用,以CGLIB为例,简要描述下动态类的加载过程。使用CGLIB生成动态代理,首先需要生成Enhancer类的实例,并制定用于处理代理业务的回调类。在enhancer.create()方法中,会使用DefaultGeneratorStrategy.Generate()方法生成代理类的字节码,并保存在byte数组中。接着调用reflectUtils.defineClass()方法,通过反射,调用ClassLoader.defineClass()方法,将字节码装载到classloader中,完成类的加载。最后,通过reflectUtils.newInstance()方法,通过反射生成动态类实例,并返回该实例。其他与该过程细节不同,但是生成逻辑相同。
猜你喜欢
- 2024-10-24 Java动态代理与静态代理以及它能为我们做什么
- 2024-10-24 Java 设计模式 之 代理模式 (1)(java设计模式之代理模式)
- 2024-10-24 Java设计模式:代理模式 vs. 装饰模式
- 2024-10-24 设计模式篇——代理模式详解(面试再问你代理模式,这么回答他)
- 2024-10-24 动态代理大揭秘,带你彻底弄清楚动态代理
- 2024-10-24 面试:Java的代理模式动态代理和静态代理区别,aop用的什么代理
- 2024-10-24 Java设计模式之代理模式(java代理类是什么)
- 2024-10-24 JAVA设计模式——代理模式(java编写代理服务)
- 2024-10-24 23种java设计模式之:门面模式、享元模式、代理模式
- 2024-10-24 Java 17中的动态代理:实现灵活的代理模式
你 发表评论:
欢迎- 最近发表
- 标签列表
-
- java反编译工具 (77)
- java反射 (57)
- java接口 (61)
- java随机数 (63)
- java7下载 (59)
- java数据结构 (61)
- java 三目运算符 (65)
- java对象转map (63)
- Java继承 (69)
- java字符串替换 (60)
- 快速排序java (59)
- java并发编程 (58)
- java api文档 (60)
- centos安装java (57)
- java调用webservice接口 (61)
- java深拷贝 (61)
- 工厂模式java (59)
- java代理模式 (59)
- java.lang (57)
- java连接mysql数据库 (67)
- java重载 (68)
- java 循环语句 (66)
- java反序列化 (58)
- java时间函数 (60)
- java是值传递还是引用传递 (62)
本文暂时没有评论,来添加一个吧(●'◡'●)