`

java动态代理原理及简单模拟

    博客分类:
  • java
阅读更多
为跳槽做打算,最近在猛学,回顾一下知识点,突然发现动态代理还是理解的模糊,狠狠研究了一天,写此文以作纪念。
首先写个普通的代理

来个接口:
public interface Drawable {
	
	public void draw();

}

再来个实现类:
public class Pen implements Drawable {

	public void draw() {
		System.out.println("draw something");
	}

}


代理类(随便在博客写,未经编译):
public class ProxyPen implements Drawable{
private Drawable draw;
public ProxyPen(Drawable draw){
this.draw = draw;
}
public viod draw(){
System.out.println("before draw");
draw.draw();
}
}
//接下来为调用代码
Drawable pen = new Pen();
ProxyPen proxy = new ProxyPen(pen);
proxy.draw();

以上的静态代理很简单,无非就是聚合+多态。
但是只能代理实现Drawable接口的类,显然具有很大局限性。
而动态代理顾名思义就是动态生成代理类,ProxyPen将根据参数动态生成,要让其动态生成显然必须取得代理的接口,取得接口后能实现代理类,但是代理类添加的内容却还是定死的System.out.println("before draw");这也不满足动态要求,所以代理内容必须也要能自定义,想输任何代理内容,当然还是多态,传入一个处理代理内容的接口Handler即可:
首先定义代理接口:
public interface InvocationHandler {
		public void invoke(Method m,Object... args) throws Exception;
}

public class Proxy {

	public static Object newProxy(Class interfaces,InvocationHandler handler) throws Exception{
		String r = "\n";
		
		Method[] methods = interfaces.getMethods();
		
		StringBuffer sb = new StringBuffer("");
		
		for(int i =0;i<methods.length;i++){
			sb.append("	public void "+methods[i].getName()+"() {"+r+
			"		try{ "+r+
			"		Method md = "+interfaces.getName()+".class.getMethod(\""+methods[i].getName()+"\");"+r+
			"		handler.invoke( md,new Object[]{});"+r+
			"		}catch(Exception e){e.printStackTrace();}"+r+	
			"	}"+r
			);
		}
		
		String src = "package com.javaeye.aronlulu.proxy;"+r+
					 "import java.lang.reflect.*;"+r+
		"public class ProxyPen implements "+interfaces.getName() +"{"+r+
	
		"	private com.javaeye.aronlulu.proxy.InvocationHandler handler;"+r+
	
		"	public ProxyPen("+handler.getClass().getName()+" handler){"+r+
		"		this.handler = handler;"+r+
		"	}"+r+
System.out.println(\"before\");"+r+

		sb.toString()+

		"}" +r;
		String dir = System.getProperty("user.dir")+"/src/com/javaeye/aronlulu/proxy/";
		FileWriter writer = new FileWriter(new File(dir+"ProxyPen.java"));
		writer.write(src);
		writer.flush();
		writer.close();
		//编译动态代理类
		JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
		StandardJavaFileManager fileMgr = compiler.getStandardFileManager(null, null, null);
		Iterable units = fileMgr.getJavaFileObjects(dir+"ProxyPen.java");
		CompilationTask t = compiler.getTask(null, fileMgr, null, null, null, units);
		t.call();
		fileMgr.close();
                  //加载并调用返回代理接口
		URL[] urls = new URL[]{new URL("file:/"+dir)};
		URLClassLoader loader = new URLClassLoader(urls);
		Class c = loader.loadClass("com.javaeye.aronlulu.proxy.ProxyPen");
		
		Constructor ctr = c.getConstructor(handler.getClass());
		return ctr.newInstance(handler);
		
	}
	
}


接下来编写具体处理代理类代码:
public class DrawHandler implements InvocationHandler {
	
	private Object draw;
	
	public DrawHandler (Object draw){
		this.draw = draw;
	}

	public void invoke(Method m,Object[] args) throws Exception{
		System.out.println("before");
		m.invoke(draw, args);
		System.out.println("after");
	}

}

测试代码:
Drawable drawable = new Pen();
InvocationHandler handler = new DrawHandler(drawable);
Drawable draw = (Drawable) Proxy.newProxy(Drawable.class,handler);
draw.draw();

动态代理的实现简单完成了,当然跟java的动态代理实现没法比,中间还封装了很多类型检查及反射实现。动态代理原理其实无非就是反射+多态+聚合的实现,当然有了动态代理,很多强大的功能就能实现了,最有名的无非就是AOP,java动态代理的局限性是只能针对接口,若要针对具体业务类,则需要CGLIB这样的第三方框架了,springAOP则采用了以上两种组合,默认还是使用java动态代理,设置Bean中一个属性开关来控制,若非接口实现,则开始调用CGLIB。
分享到:
评论
2 楼 yuyu83818578 2013-01-18  
学习了!
1 楼 jameswade 2011-08-12  

相关推荐

    java 动态代理实现,模拟spring aop

    java 动态代理实现,模拟了spring实现aop的原理,对学习面向切面编程的朋友有帮助!

    基于框架的Web开发-静态代理和动态代理原理.docx

    Java动态代理的实现 1 程序架构 创建包proxy.jdk,里面包含下面类和接口,详见批注。 类,实现了UserDao接口接口类测试类,包含main方法 类,实现了UserDao接口 接口 类 测试类,包含main方法 2 功能需求 (1) ...

    SpringAOP的实现机制(底层原理)、应用场景等详解,模拟过程的实例

    JDK动态代理: 我们将详细介绍JDK动态代理的概念和工作原理。您将了解如何使用Java的反射机制来创建代理对象,以及如何将横切逻辑注入到目标方法中。我们还提供了实际示例,演示如何在Spring AOP中使用JDK动态代理。...

    JAVA上百实例源码以及开源项目源代码

    Applet钢琴模拟程序java源码 2个目标文件,提供基本的音乐编辑功能。编辑音乐软件的朋友,这款实例会对你有所帮助。 Calendar万年历 1个目标文件 EJB 模拟银行ATM流程及操作源代码 6个目标文件,EJB来模拟银行ATM...

    JAVA上百实例源码以及开源项目

     Tcp服务端与客户端的JAVA实例源代码,一个简单的Java TCP服务器端程序,别外还有一个客户端的程序,两者互相配合可以开发出超多的网络程序,这是最基础的部分。 递归遍历矩阵 1个目标文件,简单! 多人聊天室 3...

    Java典型模块

    3.1 Java的一些简单新特性 3.1.1 静态导入 3.1.2 可变参数函数 3.1.3 增强版for循环 3.1.4 基本数据的拆、装箱操作(autoboxing和unboxing) 3.2 枚举 3.2.1 枚举的实现原理 3.2.2 枚举的简单应用 3.2.3 枚举的高级...

    Jmeter性能测试白皮书

    Jmeter也可以作为Web服务器与浏览器之间的代理网关,以便捕获浏览器的请求和Web服务器的响应。 Jmeter和其他性能工具在原理上基本一致,Jmeter包含了4个部分: 负载发生器:用于产生负载,通常以多线程或多进程的...

    使用反射技术和Facade模式演示封装数据库操作--ORM原理

    那么书写操作数据库的代码很简单:只需呼叫FacadeForDAO.findModel(表名)方法,在表名参数给出实际数据库中表的名称就可以返回一个包含对应POJO类的对象的集合--非常简单--输入表名得到Java对象的集合,然后根据需要...

    Java学习笔记-个人整理的

    {1.4.1.1}浮点数原理}{24}{subsubsection.1.4.1.1} {1.4.2}格式化输出浮点数}{24}{subsection.1.4.2} {1.4.3}\texttt {char}}{24}{subsection.1.4.3} {1.4.4}转义字符}{25}{subsection.1.4.4} {1.4.5}Boolean ...

    spring:这是Spring框架研究

    spring This is spring framework study ...五、手写动态代理功能 六、源码学习 七、模拟spring(AOP, IOC, DI, BeanPostProcessor及许多常用注解) 八、使用spring FactoryBean技术模拟mybatis MapperScan注解 ...

    Spring.3.x企业应用开发实战(完整版).part2

     Spring3.0引入了众多Java开发者翘首以盼的新功能和新特性,如OXM、校验及格式化框架、REST风格的Web编程模型等。这些新功能实用性强、易用性高,可大幅降低Java应用,特别是JavaWeb应用开发的难度,同时有效提升...

    Spring3.x企业应用开发实战(完整版) part1

     Spring3.0引入了众多Java开发者翘首以盼的新功能和新特性,如OXM、校验及格式化框架、REST风格的Web编程模型等。这些新功能实用性强、易用性高,可大幅降低Java应用,特别是JavaWeb应用开发的难度,同时有效提升...

    网络管理协议及应用开发

    3.1 SNMP的工作原理 3.2 安全识别及排序 3.2.1 列对象 3.2.2 模糊的行区分的问题 3.2.3 概念表和行对象 3.2.4 标题对象 3.2.5 按字典排序 3.3 SNMP协议数据单元 3.3.1 SNMP PDU的格式 3.3.2 SNMP消息的传输 3.3.3 ...

    proxy-istio-demo:主要描述 istio中sidecar的工作流程方便如何理解istio的

    该项目主要是模拟 从应用程序容器到Sidecar代理的流量 基本的实现原理 测试 $ curl localhost:8080 -vv -w "\n timeout ---&gt; %{time_total} \n" * Trying ::1... * TCP_NODELAY set * Connected to localhost (::...

    计算机网络(汲及内容全面)

    2.1.2 模拟通信 2.1.3 数字通信 2.2 数据通信基础理论 2.2.1 信号的频谱和带宽 2.2.2 信道的截止频率与带宽 2.2.3 信道的最大数据传输率 2.3 传输介质 2.3.1 双绞线 2.3.2 同轴电缆 2.3.3 光纤 2.3.4 无线...

    计算机网络&计算机网络

    2.1.2 模拟通信 2.1.3 数字通信 2.2 数据通信基础理论 2.2.1 信号的频谱和带宽 2.2.2 信道的截止频率与带宽 2.2.3 信道的最大数据传输率 2.3 传输介质 2.3.1 双绞线 2.3.2 同轴电缆 2.3.3 光纤 2.3.4 无线...

    计算机网络基础知识

    2.1.2 模拟通信 2.1.3 数字通信 2.2 数据通信基础理论 2.2.1 信号的频谱和带宽 2.2.2 信道的截止频率与带宽 2.2.3 信道的最大数据传输率 2.3 传输介质 2.3.1 双绞线 2.3.2 同轴电缆 2.3.3 光纤 2.3.4 无线...

Global site tag (gtag.js) - Google Analytics