为跳槽做打算,最近在猛学,回顾一下知识点,突然发现动态代理还是理解的模糊,狠狠研究了一天,写此文以作纪念。
首先写个普通的代理
来个接口:
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。
分享到:
相关推荐
java 动态代理实现,模拟了spring实现aop的原理,对学习面向切面编程的朋友有帮助!
Java动态代理的实现 1 程序架构 创建包proxy.jdk,里面包含下面类和接口,详见批注。 类,实现了UserDao接口接口类测试类,包含main方法 类,实现了UserDao接口 接口 类 测试类,包含main方法 2 功能需求 (1) ...
JDK动态代理: 我们将详细介绍JDK动态代理的概念和工作原理。您将了解如何使用Java的反射机制来创建代理对象,以及如何将横切逻辑注入到目标方法中。我们还提供了实际示例,演示如何在Spring AOP中使用JDK动态代理。...
Applet钢琴模拟程序java源码 2个目标文件,提供基本的音乐编辑功能。编辑音乐软件的朋友,这款实例会对你有所帮助。 Calendar万年历 1个目标文件 EJB 模拟银行ATM流程及操作源代码 6个目标文件,EJB来模拟银行ATM...
Tcp服务端与客户端的JAVA实例源代码,一个简单的Java TCP服务器端程序,别外还有一个客户端的程序,两者互相配合可以开发出超多的网络程序,这是最基础的部分。 递归遍历矩阵 1个目标文件,简单! 多人聊天室 3...
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也可以作为Web服务器与浏览器之间的代理网关,以便捕获浏览器的请求和Web服务器的响应。 Jmeter和其他性能工具在原理上基本一致,Jmeter包含了4个部分: 负载发生器:用于产生负载,通常以多线程或多进程的...
那么书写操作数据库的代码很简单:只需呼叫FacadeForDAO.findModel(表名)方法,在表名参数给出实际数据库中表的名称就可以返回一个包含对应POJO类的对象的集合--非常简单--输入表名得到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 This is spring framework study ...五、手写动态代理功能 六、源码学习 七、模拟spring(AOP, IOC, DI, BeanPostProcessor及许多常用注解) 八、使用spring FactoryBean技术模拟mybatis MapperScan注解 ...
Spring3.0引入了众多Java开发者翘首以盼的新功能和新特性,如OXM、校验及格式化框架、REST风格的Web编程模型等。这些新功能实用性强、易用性高,可大幅降低Java应用,特别是JavaWeb应用开发的难度,同时有效提升...
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 ...
该项目主要是模拟 从应用程序容器到Sidecar代理的流量 基本的实现原理 测试 $ curl localhost:8080 -vv -w "\n timeout ---> %{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 无线...