- 浏览: 1639028 次
- 性别:
- 来自: 北京
文章分类
- 全部博客 (405)
- C/C++ (16)
- Linux (60)
- Algorithm (41)
- ACM (8)
- Ruby (39)
- Ruby on Rails (6)
- FP (2)
- Java SE (39)
- Java EE (6)
- Spring (11)
- Hibernate (1)
- Struts (1)
- Ajax (5)
- php (2)
- Data/Web Mining (20)
- Search Engine (19)
- NLP (2)
- Machine Learning (23)
- R (0)
- Database (10)
- Data Structure (6)
- Design Pattern (16)
- Hadoop (2)
- Browser (0)
- Firefox plugin/XPCOM (8)
- Eclise development (5)
- Architecture (1)
- Server (1)
- Cache (6)
- Code Generation (3)
- Open Source Tool (5)
- Develope Tools (5)
- 读书笔记 (7)
- 备忘 (4)
- 情感 (4)
- Others (20)
- python (0)
最新评论
-
532870393:
请问下,这本书是基于Hadoop1还是Hadoop2?
Hadoop in Action简单笔记(一) -
dongbiying:
不懂呀。。
十大常用数据结构 -
bing_it:
...
使用Spring MVC HandlerExceptionResolver处理异常 -
一别梦心:
按照上面的执行,文件确实是更新了,但是还是找不到kernel, ...
virtualbox 4.08安装虚机Ubuntu11.04增强功能失败解决方法 -
dsjt:
楼主spring 什么版本,我的3.1 ,xml中配置 < ...
使用Spring MVC HandlerExceptionResolver处理异常
Java提供了动态代理,可以完成AOP和装饰模式的功能,主要的Proxy类和InvocationHandler接口:
1、Proxy类
Proxy类提供了一些工具方法:
getProxyClass得到代理类,如果不存在则动态创建。
newProxyInstance创建一个代理实例。
isProxyClass判断是否是一个代理类。
getInvocationHandler得到InvocationHandler。
一般先调用isProxyClass,判断是,然后再使用getInvocationHandler
参数:loader,创建对象需要classLoader,创建proxy也需要,一般被代理
真实对象得到:realObj.getClass().getClassLoader();
interfaces,代理和真实对象实现的接口。
创建一个代理一般使用以下两种方式:
方法一:
方法二:
2、InvocationHandler接口:
代理对象通过这个接口来将真实的对象联系起来。过程是:
代理对象直接调用InvocationHandler 的invoke方法,把自己作为proxy参数,调用的函数
作为method参数,调用函数的参数作为args传递过来,我们只需要在invoke方法中做一些事情,然后再调用被代理对象的方法就可以了。
我们以一个例子说明:
跟踪函数的调用过程:
函数执行之前和之后打印出跟踪信息:
实现InvocationHandler接口:
我们测试一下:
Java动态代理的缺点是只能对接口进行代理,无法代理class。
3.高级进阶:
如果我们想象拦截器那样一层一层的拦截,也就是形成一个代理链,上面的实现可能会出现问题,比如我们想有个同步调用方法的代理,如果按照上面的实现
IHelloWorld tc = (IHelloWorld) MethodSynchronizer.createProxy(
MethodTracker.createProxy(new HelloWorld(),new PrintWriter(System.out,true))
);
将是错误的,因为他使用的同步对象是内层代理,而不是真实要被代理的对象。
要完成上面的功能,我们可以通过下面实现来达到:
注意,这里我们约定了实现InvocationHandler接口的类使用target字段来保存被代理的对象,通过继承InvocationHandlerBase便可以达到所说的效果:
测试代码:
1、Proxy类
public class Proxy implements java.io.Serializable { //... public static Class getProxyClass( ClassLoader loader, Class[] interfaces )throws IllegalArgumentException; public static Object newProxyInstance( ClassLoader loader, Class[] interfaces,InvocationHandler h )throws IllegalArgumentException; public static boolean isProxyClass( Class cl ); public static InvocationHandler getInvocationHandler( Object proxy ) throws IllegalArgumentException; }
Proxy类提供了一些工具方法:
getProxyClass得到代理类,如果不存在则动态创建。
newProxyInstance创建一个代理实例。
isProxyClass判断是否是一个代理类。
getInvocationHandler得到InvocationHandler。
一般先调用isProxyClass,判断是,然后再使用getInvocationHandler
参数:loader,创建对象需要classLoader,创建proxy也需要,一般被代理
真实对象得到:realObj.getClass().getClassLoader();
interfaces,代理和真实对象实现的接口。
创建一个代理一般使用以下两种方式:
方法一:
Proxy cl = getProxyClass( SomeInterface.getClassLoader(), Class[]{SomeInterface.class} ); Constructor cons = cl.getConstructor( new Class[]{InvocationHandler.class} ); Object proxy = cons.newInstance( new Object[] { new SomeIH( obj ) } );
方法二:
Object proxy = Proxy.newProxyInstance( SomeInterface.getClassLoader(), Class[]{SomeInterface.class}, new SomeIH( obj ) );
2、InvocationHandler接口:
public interface InvocationHandler { public Object invoke( Object proxy, Method method, Object[] args ) throws Throwable; }
代理对象通过这个接口来将真实的对象联系起来。过程是:
代理对象直接调用InvocationHandler 的invoke方法,把自己作为proxy参数,调用的函数
作为method参数,调用函数的参数作为args传递过来,我们只需要在invoke方法中做一些事情,然后再调用被代理对象的方法就可以了。
我们以一个例子说明:
跟踪函数的调用过程:
函数执行之前和之后打印出跟踪信息:
实现InvocationHandler接口:
import java.io.PrintWriter; import java.lang.reflect.InvocationHandler; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.Proxy; public class MethodTracker implements InvocationHandler{; private Object target; private PrintWriter out; private MethodTracker(Object obj, PrintWriter out){ this.target = obj; this.out = out; } public static Object createProxy(Object obj, PrintWriter out){ return Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), new MethodTracker(obj,out)); } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { Object result = null; try{ out.println(method.getName() + "(...) called"); result = method.invoke(target, args); }catch(InvocationTargetException e){ out.println(method.getName() + " throws " + e.getCause()); throw e.getCause(); } out.println(method.getName() + " returns"); return result; } }
我们测试一下:
import java.io.PrintWriter; interface IHelloWorld{ void hello(); } class HelloWorld implements IHelloWorld{ private String name = "world"; public void hello(){ System.out.println("Hello," + name); } public void setName(String name){ this.name = name; } } public class TestTracker { public static void main(String[] args) { IHelloWorld tc = (IHelloWorld) MethodTracker.createProxy(new HelloWorld(),new PrintWriter(System.out,true)); tc.hello(); } }
Java动态代理的缺点是只能对接口进行代理,无法代理class。
3.高级进阶:
如果我们想象拦截器那样一层一层的拦截,也就是形成一个代理链,上面的实现可能会出现问题,比如我们想有个同步调用方法的代理,如果按照上面的实现
IHelloWorld tc = (IHelloWorld) MethodSynchronizer.createProxy(
MethodTracker.createProxy(new HelloWorld(),new PrintWriter(System.out,true))
);
将是错误的,因为他使用的同步对象是内层代理,而不是真实要被代理的对象。
要完成上面的功能,我们可以通过下面实现来达到:
import java.lang.reflect.Field; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Proxy; public abstract class InvocationHandlerBase implements InvocationHandler{ protected Object nextTarget; protected Object realTarget = null; public InvocationHandlerBase(Object target){ nextTarget = target; if(nextTarget != null){ realTarget = findRealTarget(nextTarget); if(realTarget == null){ throw new RuntimeException("findRealTarget failure"); } } } protected final Object getRealTarget(){ return realTarget; } protected static final Object findRealTarget(Object t){ if(! Proxy.isProxyClass(t.getClass())) return t; InvocationHandler ih = Proxy.getInvocationHandler(t); if(InvocationHandlerBase.class.isInstance(ih)){ return ((InvocationHandlerBase)ih).getRealTarget(); }else{ try{ Field f = findField(ih.getClass(), "target"); if(Object.class.isAssignableFrom(f.getType())&& ! f.getType().isArray()){ f.setAccessible(true); Object innerTarget = f.get(ih); return findRealTarget(innerTarget); } return null; }catch(Exception e){ return null; } } } public static Field findField(Class<?> cls, String name) throws NoSuchFieldException{ if(cls != null){ try{ return cls.getDeclaredField(name); }catch(NoSuchFieldException e){ return findField(cls.getSuperclass(),name); } }else{ throw new NoSuchFieldException(); } } }
注意,这里我们约定了实现InvocationHandler接口的类使用target字段来保存被代理的对象,通过继承InvocationHandlerBase便可以达到所说的效果:
import java.lang.reflect.Method; import java.lang.reflect.Proxy; public class MethodSynchronizer extends InvocationHandlerBase{ public static Object createProxy(Object obj){ return Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), new MethodSynchronizer(obj)); } private MethodSynchronizer(Object obj){ super(obj); } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { Object result = null; synchronized( this.getRealTarget() ){ result = method.invoke(nextTarget, args); } return result; } }
测试代码:
import java.io.PrintWriter; interface IHelloWorld{ void hello(); } class HelloWorld implements IHelloWorld{ private String name = "world"; public void hello(){ System.out.println("Hello," + name); } public void setName(String name){ this.name = name; } } public class TestTracker { public static void main(String[] args) { IHelloWorld tc = (IHelloWorld) MethodSynchronizer.createProxy( MethodTracker.createProxy(new HelloWorld(),new PrintWriter(System.out,true)) ); tc.hello(); } }
发表评论
-
Builder模式遇到继承
2013-10-13 13:48 0interface Self<T extends ... -
Builder模式遇到集成
2013-10-13 13:47 0package com.qunar.qss.business. ... -
JVM调优Step by Step
2012-02-02 17:38 0现代的JVM能够适应于各种应用和领域,每个应用和领域的使用 ... -
commons-lang StringUtils#split的坑
2011-12-31 10:11 3118今天用StringUtils#split,陷入了前两个坑。需求 ... -
使用scala.sys.process包和系统交互
2011-07-19 00:00 6448在Java中我们可以使用Runtime.getRuntime( ... -
HttpClient Json请求工具
2011-05-05 18:32 17809发送Json请求,结果返回Json. public sta ... -
利用Java反射实现通用的Excel报表
2011-04-12 16:00 1987最近有很多客户报表需要提供客户下载,需要生成一个Excel的格 ... -
深入异常处理
2011-03-31 20:46 1777异常处理是写一个健壮 ... -
Java序列化注意一些点
2011-03-12 21:04 18181.序列化ID的问题: 标示了版本号,版本号一致才能反序列化成 ... -
Java Timestamp是和ExtJS的timestamp不兼容
2010-08-09 20:33 3329Timestamp纳秒级别的,ExtJS的timestamp使 ... -
XML DocumentBuilder#parse(String str)
2010-07-06 15:55 3856DocumentBuilderFactory dbf = ... -
[备忘]String#split/substring的子串会共享原来大的String
2010-03-29 17:18 1454如果每次需要大字符串中的很小的一个字串,可能会引起内存中大量的 ... -
runtime.exec()执行进程block死锁问题
2010-01-18 21:39 5236最近在java代码中使用runtime.exec执行rsync ... -
URL中文问题
2010-01-08 14:46 10479最近使用HttpClient,和Java的java.net.U ... -
A TaskExecutor Impl
2009-12-07 11:33 1588import java.util.ArrayList; im ... -
使用XStream把Java对象XML/JSON格式的序列化和反序列化
2009-05-05 11:37 6194试了一下Thoughtworks的XStream,以测试驱动和 ... -
从《编程的未来》这篇文章想到C++和Java语言的爽与不爽
2009-05-01 23:44 3939从编程的未来这篇文 ... -
《Effetive Java》读书笔记二
2009-02-23 14:23 1570第二章 所有对象共有的 ... -
《Effetive Java》读书笔记一
2009-02-19 11:36 2141《Effetive Java》和 《Effective C++ ... -
如何彻底杜绝别人使用你的类
2008-05-22 19:30 2324今天在eclipse源码中发 ...
相关推荐
java动态代理实例 要想理解拦截器的知识 最好要先理解java动态代理这块
java动态代理 public class HireProxy implements InvocationHandler { //被代理的真实角色 private Object obj; public HireProxy(Object obj) { super(); this.obj = obj; } //第二个参数method,被...
Java 动态代理详解(学习资料);Java 动态代理详解(学习资料);Java 动态代理详解(学习资料);Java 动态代理详解(学习资料);Java 动态代理详解(学习资料);
适用于初探java动态代理模式,精简易懂。
对代理模式与Java动态代理类的理解说明
java 动态代理 简单实例 新手看看
Java动态代理的helloworld,抛砖引玉吧
描述java动态代理,说明了怎么实现java的动态代理
Java 动态代理 借用电子商务模式来说明
更好的了解java动态代理的原理!
java动态代理 经典文章(word 2007格式的) 要用word 2007看
一个简单的java动态代理的实例
用Java动态代理实现AOP,讲的很好(用Java动态代理实现AOP)
Java动态代理实现数据源连接池,用代理类实现的连接池代码,绝对完整的案例,下载源码就能跑起来!Java动态代理实现数据源连接池,用代理类实现的连接池代码
Java动态代理类位于Java.lang.reflect包下,一般主要涉及到以下两个类: (1) Interface InvocationHandler (2) Proxy:该类即为动态代理类,
Java动态代理类位于Java.lang.reflect包下,一般主要涉及到以下两个类: (1) Interface InvocationHandler (2) Proxy:该类即为动态代理类,
java动态代理项目实践优化(3)
Java实现动态代理的两种方式。 相对来说cglib更加方便。可以实现为实现接口的类(非final类)
java动态代理 完整版 java动态代理 完整版 java动态代理 完整版 java动态代理 完整版 java动态代理 完整版
java动态代理的机制分析,以及相应的拓展。有详细的代码和实例加以分析。