`
kylinsoong
  • 浏览: 240724 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

Proxy

    博客分类:
  • JAVA
阅读更多

1. 从一个简单例子开始,如下定义一个接口和一个接口实现:

public interface Moveable {
	public void move();
}

 

public class Person implements Moveable {
	public void move() {
		System.out.println("Person remove");
	}
}

 

      现在要做的在人移动之前记录时间和输出日志,并且记录时间和输出日志的顺序可以任意控制,这中情况可以用静态代理来简单模拟,如下:



 如上图,记录日志和时间可以通过两个Person的代理俩完成,两个代码如下:

 

public class PersonLogProxy implements Moveable {
	private Moveable entity;
	public PersonLogProxy(Moveable entity) {
		this.entity = entity;
	}
	public void move() {
		System.out.println("[" + new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.S'Z'").format(new Date()) + " Person move start]");
		entity.move();
		System.out.println("[" +  new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.S'Z'").format(new Date()) + " Person move End]");
	}
}

 

public class PersonTimeProxy implements Moveable {
	private Moveable entity;
	public PersonTimeProxy(Moveable entity) {
		this.entity = entity;
	}
	public void move() {
		Date start = new Date();
		System.out.println("START...");
		entity.move();
		System.out.println("END, TOTAL APENT: " + (new Date().getTime() - start.getTime()) + " MILLISECONDS.");
	}
}

  

如我们提出的问题,我们要实现先记录日志,再记录时间,可以执行下面代码:

Moveable person = new Person();
		Moveable timeProxy = new PersonTimeProxy(person);
		Moveable logProxy = new PersonLogProxy(timeProxy);
		logProxy.move();

 

运行结果:

[2010-08-30T17:15:09.437Z Person move start]
START...
Person remove
END, TOTAL APENT: 3984 MILLISECONDS.
[2010-08-30T17:15:13.437Z Person move End]

 

此种情况可以用下面时序图描述



 PersonLogProxy调运PersonTimeProxy,然后PersonTimeProxcy调运Person执行move方法,然后依次返回结束;

如我们要实现先记录时间,再记录日志,可以执行下面代码:

Moveable person = new Person();
		Moveable logProxy = new PersonLogProxy(person);
		Moveable timeProxy = new PersonTimeProxy(logProxy);
		timeProxy.move();

 

运行结果;

START...
[2010-08-30T17:23:27.281Z Person move start]
Person remove
[2010-08-30T17:23:29.453Z Person move End]
END, TOTAL APENT: 2203 MILLISECONDS.

 

同样先记录时间,在记录日志可以用下图说明



 PersonTimeProxy调运PersonLogProxy,然后PersonTimeProxcy调运Person执行move方法,然后依次返回结束;

      上面过程为简单静态代理,PersonTimeProxy和PersonLogProxy为Person代理,通过这种方式可以灵活实现先记录日志,或先记录时间的逻辑控制。

2. 动态代理开始

动态代理从字面上理解就是所需的代理类如上面PersonTimeProxy等不需要我们手动去完成,而是由程序动态的生成;java.lang.reflect.Proxy是JDK中用来产生动态代理的类,我们先简单模仿java.lang.reflect.Proxy生成动态代理类的过程,以动态生成运行PersonTimeProxy为例来说明,如下图所示:
 

      如上图所示要完成动态生成Person的时间代理大致需要3个步骤:

      第一:生成PersonTimeProxy.java临时文件,此文件是一个Java文件,实际JDK包中它没有删除文件,而是直接生成二进制文件;

      第二:编译第一步生成的文件,.java文件需要编译成.class文件才可以运行,所以这一步主要是如何将PersonTimeProxy.java编译成PersonTimeProxy.class文件;

      第三:运行第二步产生的PersonTimeProxy.class文件,首先需要将其加载到内存中,常用加载.class文件的方式是java.lang.ClassLoader及其子类,这里用URLClassLoader(),因为URLClassLoader不需要从他父类获得(其他的类加载器都需要从他的父类获得):

按照上面三步给出我写的代码:

package com.learn.proxy.test;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;

import javax.tools.JavaCompiler;
import javax.tools.JavaCompiler.CompilationTask;
import javax.tools.StandardJavaFileManager;
import javax.tools.ToolProvider;

import com.learn.proxy.dynamic.Moveable;
import com.learn.proxy.dynamic.Person;

public class DynamicProxySimulation {

	public static void main(String[] args) throws IOException, ClassNotFoundException, SecurityException, NoSuchMethodException, IllegalArgumentException, InstantiationException, IllegalAccessException, InvocationTargetException {
		//Step 1
		String str = 
			"	package com.learn.proxy.dynamic;      " + "\r\n" +
		    "                                         " + "\r\n" +
			"	import java.util.Date;                " + "\r\n" +
		    "                                         " + "\r\n" +
			"	public class PersonTimeProxy implements Moveable {   " + "\r\n" +
			"		private Moveable entity;                         " + "\r\n" +
			"		public PersonTimeProxy(Moveable entity) {        " + "\r\n" +
			"			this.entity = entity;                        " + "\r\n" +
			"		}                                                " + "\r\n" +
			"		public void move() {                             " + "\r\n" +
			"			Date start = new Date();                     " + "\r\n" +
			"			System.out.println(\"START...\");              " + "\r\n" +
			"			entity.move();                               " + "\r\n" +
			"			System.out.println(\"END, TOTAL APENT: \" + (new Date().getTime() - start.getTime()) + \" MILLISECONDS.\");" + "\r\n" +
			"		}                                                " + "\r\n" +
			"		                                                 " + "\r\n" +
			"	}                                                    " + "\r\n" ;
		String fileName = System.getProperty("user.dir") + "/proxy/com/learn/proxy/dynamic/PersonTimeProxy.java";
		File file = new File(fileName);
		FileWriter writer = new FileWriter(file);
		writer.write(str);
		writer.flush();
		writer.close();
		
		//Step 2
		JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
		StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, null, null);
		Iterable units = fileManager.getJavaFileObjects(fileName);
		CompilationTask task = compiler.getTask(null, fileManager, null, null, null, units);
		task.call();
		fileManager.close();
		file.delete();
		
		//Step 3
		fileName = fileName.substring(0, fileName.length()- 4) + "class";
		URL[] urls = new URL[]{new URL("file://" + System.getProperty("user.dir") + "/proxy/")};
		URLClassLoader urlClassLoader = new URLClassLoader(urls);
		Class c = urlClassLoader.loadClass("com.learn.proxy.dynamic.PersonTimeProxy");
		
		//Step 4
		Constructor ctr = c.getDeclaredConstructor(Moveable.class);
		Moveable m = (Moveable) ctr.newInstance(new Person());
		m.move();
	}

}

 

上面代码中多出的第四步是验证代码,运行后结果如下:

START...
Person remove
END, TOTAL APENT: 8110 MILLISECONDS.

 

结果显示记录了人移动的时间。

分析:在动态代理开始种虽然我们没有类PersonTimeProxy,但我们却通过DynamicProxySimulation类完成了静态的 PersonTimeProxy类的功能如上就是简单的动态代理原理;

 

PS……接下来先继续模拟java.lang.reflect.Proxy,然后总的分析JDK中的java.lang.reflect.Proxy

  • 大小: 8.4 KB
  • 大小: 5.5 KB
  • 大小: 5.8 KB
  • 大小: 19.3 KB
分享到:
评论

相关推荐

    proxy.jsp、proxy.ashx、proxy.php、proxy.config

    配置时同样需要将`proxy.ashx`部署到服务器,并在ArcGIS JavaScript API中设置`proxyUrl`属性。 **proxy.php** 是PHP语言实现的代理服务,适用于PHP环境,如Apache或Nginx。对于那些基于PHP的Web应用,可以使用`...

    OPC COM ProxyStub MergeModule (x86)_foundation_proxy_usvfs_proxy

    Proxy和Stub的作用是解决进程间通信的问题,使得不同地址空间的应用程序可以透明地调用彼此的功能。 3. **MergeModule (x86)**:MergeModule是一个MSI(Microsoft Installer)模块,用于将组件打包到安装程序中。...

    ABAP 调用ABAP PROXY

    在SAP系统中,ABAP调用ABAP Proxy是一种常见的技术操作,用于在不同系统间或者同一系统内的组件之间实现通信。ABAP Proxy是SAP提供的一个强大的接口技术,它允许开发者创建安全、高效的远程调用机制。接下来,我们将...

    goproxy-android snail007/goproxy全能代理服务器安卓版

    《GoProxy-Android:全能代理服务器在安卓平台的应用与实现》 GoProxy-Android是由snail007/goproxy团队开发的一款适用于安卓系统的全能代理服务器应用。此项目旨在为移动设备提供强大的网络代理功能,使得用户能够...

    Nginx之proxy_redirect使用详解

    在讨论Nginx的proxy_redirect指令时,我们首先要明确其在Nginx配置中的作用和重要性。proxy_redirect指令主要用于在反向代理过程中修改响应头中的Location和Refresh字段值。在Web服务器配置中,特别是在使用Nginx...

    sharding-proxy实现分表

    接下来我们将深入探讨标题和描述中涉及的“sharding-proxy实现分表”这一主题。 ### 1. 分库分表介绍 分库分表是数据库水平扩展的一种常见策略,用于解决单表数据量过大导致的性能问题。随着业务的增长,数据量...

    foxyproxy_standard

    FoxyProxy 是一款高级代理服务器管理工具,是 Firefox 火狐浏览器的代理插件,相比比 SwitchProxy、ProxyButton、QuickProxy、xyzproxy、ProxyTex 等扩展提供更多的功能。 FoxyProxy 通过使用通配符、正则表达式和...

    influx-proxy-2.5.7-linux-amd64.tar.gz

    《InfluxDB与Influx-Proxy的深度解析》 InfluxDB是一款专为时间序列数据设计的开源数据库,尤其在监控、物联网(IoT)、性能指标和其他大数据领域有着广泛的应用。而"Influx-proxy"则可能是一个针对InfluxDB的代理...

    Proxy SwitchOmega 2.5.15 Chrome离线插件(谷歌浏览器proxy插件)

    Google Chrome插件: Proxy SwitchOmega 2.5.15. 轻松快捷地管理和切换多个代理设置. 离线插件使用方法: 1. 打开Chrome -> 自定义及控制按钮(右上角) -> 更多工具 -> 扩展程序 (有可能需要打开开发者模式) 2. 拖拽...

    ArcGIS JS API跨域配置 Proxy 代理

    "ArcGIS JS API跨域配置 Proxy 代理" ArcGIS JS API 跨域配置是指在 JS 开发中遇到的访问本地服务和外网服务的问题,需要使用 Proxy 代理来解决跨域访问文件的问题。ArcGIS 的帮助中已经有了相关的介绍和使用配置。...

    proxy与mycat对比测试

    Proxy和Mycat是两种常用的中间件,用于实现这些功能。本篇文章将深入探讨proxy和Mycat的对比测试,以及如何在MySQL主从架构中进行测试。 首先,我们来看proxy。Proxy通常指的是数据库代理服务器,它位于应用服务器...

    Petalinux dma-proxy.已测可用,注意参数一致

    `dma-proxy.c`、`dma-proxy-test.c`、`dma-proxy.h` 这些文件名暗示了它们在实现或测试dma-proxy的功能中起到的作用: 1. `dma-proxy.c`: 这通常是一个C语言源代码文件,其中包含了dma-proxy的主要实现逻辑。它可能...

    proxy代理程序实例和讲解

    在本文中,我们将深入探讨“proxy代理程序”的概念以及如何实现一个简单的代理服务。网络编程是计算机科学中的一个重要领域,而代理程序在此中扮演着关键角色,它允许客户端通过中间服务器来访问其他网络资源,从而...

    mysql-proxy-0.8.5-windows-x86-32bit

    MySQL Proxy 是一个开源工具,由 MySQL AB 公司开发,允许用户在 MySQL 客户端和服务器之间插入一个代理层。这个代理层可以用来监控、分析或者修改通信数据,为数据库管理提供了一种灵活的解决方案。`mysql-proxy-...

    ftpproxy-1.2.3.rar_Linux c proxy_ftpproxy_ftp代理_linux ftp_proxy-

    proxy源代码,linux下的ftp 代理的源代码,大家多多支持啊

    Java_ProxyServer.rar_Java ProxyServer_java proxy server

    Java ProxyServer是一个基于Java实现的代理服务器类,它在客户端和服务器之间起到了中继的作用,允许数据在两者间传输。代理服务器在计算机网络中的主要功能是提供代理服务,它可以隐藏客户端的真实身份,增加网络...

    charles-proxy-4.6.5-win64

    Charles Proxy主要用于Web开发中,以便于开发者调试和测试其网站或应用程序的网络服务。 版本4.6.5是Charles Proxy的一个特定版本,作为一款成熟的工具,它具有以下几个主要功能: 网络请求和响应查看:Charles...

    proxy2proxy多级协议代理软件-v1.0.2.129版本

     proxy2proxy 多级协议代理软件当前支持32/64位Windows7/8/10等操作系统。  proxy2proxy 多级协议代理软件特点:  1)支持单级/多级协议代理服务。  2)支持 HTTP/HTTPS 协议网络代理。  3)支持大规模网络...

Global site tag (gtag.js) - Google Analytics