`
kylinsoong
  • 浏览: 236129 次
  • 性别: 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
分享到:
评论

相关推荐

    foxyproxy_standard

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

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

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

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

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

    Nginx之proxy_redirect使用详解

    所以在这里用到了nginx的proxy_redirect指定修改被代理服务器返回的响应头中的location头域跟refresh头域数值 以下是截取nginx的一小段配置文档 server { listen 80; server_name www.boke.com; l

    apache Proxy_Error

    apache Proxy Error apache Proxy Error apache Proxy Error apache Proxy Error

    ABAP 调用ABAP PROXY

    ABAP 调用ABAP PROXY

    火狐浏览器代理插件foxyproxy与SwitchyOmega.rar

    1、FoxyProxy是一个高级的代理管理工具,它完全替代了Firefox有限的代理功能。它提供比SwitchProxy、ProxyButton、 QuickProxy、xyzproxy、ProxyTex、TorButton等等更多的功能。 2、装完Firefox的Foxyproxy插件后,...

    proxy lab参考答案

    2014最新版proxy lab参考答案,小伙伴快来吧!

    Github Python ProxyPool(代理池)

    简易高效的代理池,提供如下功能: 1. 定时抓取免费代理网站,简易可扩展 2. 使用 Redis 对代理进行存储...Github 链接:https://github.com/Python3WebSpider/ProxyPool 详情阅读:README.md,使用方法及相关信息讲解

    MySQL Proxy 实现负载均衡测试

    MySQL Proxy 实现负载均衡测试 MySQL Proxy 实现负载均衡测试

    Elite Proxy Switcher Pro v1.27

    它是很棒的Proxy(代理服务)验证、切换工具,如需下载Proxy List需要购买订阅服务,或者从另一个工具Proxy Switcher PRO导出代理列表。这个注册版仅供学习、研究使用,如需商用或者个人有充足预算,请到官网购买...

    Elite Proxy Switcher Pro v1.24

    Elite Proxy Switcher Pro v1.24 是目前从国外论坛找到的零售注册版,官网的新版本只是免费版(只有会员购买后才可以下载专业版),免费版无法激活。它是很棒的Proxy(代理服务)验证、切换工具,如需下载Proxy List...

    tftp_proxy源码

    Tftp ProxyServer 代理服务器 源码 *=========================================================================== * * Project: tftp_proxy, a proxy for TFTP transfers through firewalls * File: tftp_...

    sharding-proxy实现分表

    使用mysql5.7+sharding-proxy实现分表,策略为每半年时间分一次表

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

    esri.config.defaults.io.proxyUrl is not set所缺文件 proxy.jsp、proxy.ashx、proxy.php、proxy.config

    kube-proxy-temp-1.16.8.yaml

    aws-kube-proxy1.16.8版本示例文件

    netty-handler-proxy-4.1.68.Final-API文档-中文版.zip

    赠送jar包:netty-handler-proxy-4.1.68.Final.jar; 赠送原API文档:netty-handler-proxy-4.1.68.Final-javadoc.jar; 赠送源代码:netty-handler-proxy-4.1.68.Final-sources.jar; 赠送Maven依赖信息文件:netty-...

    ICS lab10 WebProxy

    ICS lab10 WebProxy 包含 proxy.c

    proxy代理程序实例和讲解

    proxy代理程序实例和讲解 网络编程详细代码实现和讲解

Global site tag (gtag.js) - Google Analytics