博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Java程序性能优化之代理模式
阅读量:5326 次
发布时间:2019-06-14

本文共 2894 字,大约阅读时间需要 9 分钟。

 

代理模式的用处很多,有的是为了系统安全,有的是为了远程调用,这里我们,主要探讨下由于程序性能优化的延迟加载。

首先我们来看下代理模式设计

先首先简单阐述下什么叫代理模式吧

代理设计模式有一个接口,另外还有真实主题类和代理类,真实类和代理类都实现了接口,代理类和真实主题类是关联和聚合关系。客户端与接口关联。

代理分为静态代理和动代态代理所谓静态代理是为真实主题手动创建一个代理,而动态代理则是jvm在运行时运用字节码加载技术自动创建一个代理,并不用关心接口和真是主题类

具体如何实现

哦,对了差点忘了。代理模式到底是怎样优化程序的,我们具体来看下。

客户端测试代码如下:

public class TestDynamicProxy {		public static void main(String[] args) {					IDBQuery iy = JdkDBqueryHandler.createJdkProxy();			System.out.println(iy.request());				}}

 

Ps:客户端与接口关联

代理实现和逻辑处理类如下:

import java.lang.reflect.*;	public class JdkDBqueryHandler implements InvocationHandler{			IDBQuery real = null;			public Object invoke(Object object, Method method ,Object[] args ) {				if(real==null) {									real = new DBQuery();				}				return real.request();							}	public static IDBQuery createJdkProxy() {				IDBQuery jdkProxy = (IDBQuery)Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(),new Class[]{IDBQuery.class},new JdkDBqueryHandler());				return jdkProxy;			}	}

  

Ps:代理实现和逻辑处理类是实现延迟加载的关键代码

当客户端开始加载时会加载到代码实现和逻辑处理类并创建代理实例,但并不会初始化真实主题类。只有当调用iy.request()方法时才会执行代理实现和逻辑处理类的invoke()方法并加载并初始化真实主题类。这样才实现了延迟加载,减少系统初始化时间,提高用户体验。在一定程度上也可以节约内存空间,避免内存空间浪费,(因为用的时候才记载初始化的嘛,不用也开辟内存空间那不是浪费了嘛)

这里另外附上接口类和真实主题类的代码,方便大家测试

接口类

public interface  IDBQuery {       String request();}

真实主题类 

public class  DBQuery implements IDBQuery {				public DBQuery() {				try{ 							Thread.sleep(1000);											}catch(InterruptedException e) {										e.printStackTrace();				}				}		public String request() {			 			return "request coming";				}		}

以上是jdk自带的动态代理实现 另外还有较流行的CGLIB动态代理,javaassist动态代理

这里我先介绍一下CGLIB动态代理。CGLIB动态代理和jdk的动态代理非常的相似,我们来看下具体的代码

客户端代码如下:

public class TestDynamicProxy {		public static void main(String[] args) {					IDBQuery iy = CglibDbQueryInterceptor.createCglibProxy();			System.out.println(iy.request());				}}

这里不过多解释,看完上面的例子相信大家都明白了

代理实现和逻辑处理类如下

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 CglibDbQueryInterceptor implements MethodInterceptor{		IDBQuery real = null;				public Object intercept(Object args0,Method arg1,Object[] args2,MethodProxy args3)throws Throwable {			if(real==null) {				real = new DBQuery();						}			return real.request();				} 		public static IDBQuery createCglibProxy() {					Enhancer eh = new Enhancer();			eh.setCallback(new CglibDbQueryInterceptor());//指定切入器,定义代理类逻辑			eh.setInterfaces(new Class[]{IDBQuery.class});//指定接口			IDBQuery proxy = (IDBQuery)eh.create();//创建代理实例			return proxy;				}}

  

Jdk的动态代理和CGLIB实现动态代理大致都要指定代理类逻辑和代理接口这是共性

真实主题类和接口和上例一样,不再贴了

JavaAssist的动态代理有两种实现方法,一种使用代理工厂,一种使用动态java代码生成字节码

这里就直接贴代码了:

图片上传失败~~~

Ps:以上实例方法在在逻辑处理类中处理类,真实主题类和接口和上面例子相同

代理工厂指定接口后生成代理类对象,代理类对象再指定处理逻辑。

大致三者都相似,javaAssist动态java代码生成字节码就不介绍了,赶觉较麻烦

另有ASM动态代理实现起来比较复杂,也不介绍

 

 

 

 

 

 

  

  

 

 

转载于:https://www.cnblogs.com/kimoyoyo21/p/4771628.html

你可能感兴趣的文章
Luogu P3172 [CQOI2015]选数
查看>>
spring 之 BeanFactory
查看>>
wordpress迁移服务器指南
查看>>
快速排序法
查看>>
C/C++中的预编译指令
查看>>
C# 标签的添加和删除(选择标签加样式)
查看>>
SpringMvc 大概流程分析
查看>>
JMeter记录篇5——JMeter体系结构
查看>>
读写(I/O)辩论
查看>>
Jmeter (一) 安装
查看>>
grep文本搜索工具详解
查看>>
2016031801 - 给移动硬盘分区
查看>>
Android Toast小解
查看>>
数据结构与算法问题 二叉排序树
查看>>
JAVA获取操作系统的信息
查看>>
[DLX精确覆盖+打表] hdu 2518 Dominoes
查看>>
使用 Python 把多个 MP4 合成一个视频(转)
查看>>
php 递归无线级别分类
查看>>
Struts2 简单的增删改查
查看>>
浏览器F12之后-----你不一定不知道的事
查看>>