- 浏览: 1653406 次
- 性别:
- 来自: 北京
文章分类
- 全部博客 (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 3151今天用StringUtils#split,陷入了前两个坑。需求 ... -
使用scala.sys.process包和系统交互
2011-07-19 00:00 6489在Java中我们可以使用Runtime.getRuntime( ... -
HttpClient Json请求工具
2011-05-05 18:32 17847发送Json请求,结果返回Json. public sta ... -
利用Java反射实现通用的Excel报表
2011-04-12 16:00 2016最近有很多客户报表需要提供客户下载,需要生成一个Excel的格 ... -
深入异常处理
2011-03-31 20:46 1798异常处理是写一个健壮 ... -
Java序列化注意一些点
2011-03-12 21:04 18431.序列化ID的问题: 标示了版本号,版本号一致才能反序列化成 ... -
Java Timestamp是和ExtJS的timestamp不兼容
2010-08-09 20:33 3351Timestamp纳秒级别的,ExtJS的timestamp使 ... -
XML DocumentBuilder#parse(String str)
2010-07-06 15:55 3884DocumentBuilderFactory dbf = ... -
[备忘]String#split/substring的子串会共享原来大的String
2010-03-29 17:18 1488如果每次需要大字符串中的很小的一个字串,可能会引起内存中大量的 ... -
runtime.exec()执行进程block死锁问题
2010-01-18 21:39 5284最近在java代码中使用runtime.exec执行rsync ... -
URL中文问题
2010-01-08 14:46 10523最近使用HttpClient,和Java的java.net.U ... -
A TaskExecutor Impl
2009-12-07 11:33 1624import java.util.ArrayList; im ... -
使用XStream把Java对象XML/JSON格式的序列化和反序列化
2009-05-05 11:37 6235试了一下Thoughtworks的XStream,以测试驱动和 ... -
从《编程的未来》这篇文章想到C++和Java语言的爽与不爽
2009-05-01 23:44 3966从编程的未来这篇文 ... -
《Effetive Java》读书笔记二
2009-02-23 14:23 1601第二章 所有对象共有的 ... -
《Effetive Java》读书笔记一
2009-02-19 11:36 2180《Effetive Java》和 《Effective C++ ... -
如何彻底杜绝别人使用你的类
2008-05-22 19:30 2355今天在eclipse源码中发 ...
相关推荐
Java动态代理是Java编程中一个重要的特性,它允许我们在运行时创建代理对象,这些代理对象可以代表并增强原对象的功能。动态代理在很多场景下都非常有用,比如日志记录、性能监控、事务管理等。本示例将带你深入理解...
Java动态代理是Java语言提供的一种在运行时创建代理对象的技术,它允许我们为已存在的接口创建代理类,以便在调用真实目标对象的方法时添加额外的功能或行为。在这个实例中,我们将深入探讨Java动态代理的核心概念,...
Java动态代理是Java编程中一个重要的特性,它允许在运行时创建代理对象,这些代理对象可以代表并增强原对象的功能。动态代理主要应用于面向切面编程(AOP)和事件监听等场景,使得代码更加模块化,易于维护。以下是...
Java动态代理技术是Java编程中一个非常重要的特性,它允许我们在运行时动态创建具有特定行为的对象。这种技术常用于AOP(面向切面编程)和框架中,如Spring AOP,用于实现方法拦截、事务管理等功能。Java提供了两种...
本篇文章将深入探讨Java动态代理的概念、原理以及如何通过一个简单的"Hello, World!"示例来理解它。 动态代理,顾名思义,是在程序运行时动态地生成代理对象。与静态代理(编译时已知)相比,动态代理更加灵活,...
JDK 动态代理JDK 提供了 java.lang.reflect.Proxy 类和 java.lang.reflect.InvocationHandler 接口来支持动态代理。Proxy 类用于创建一个代理对象,而 InvocationHandler 接口则定义了代理对象的方法调用处理逻辑。...
Java动态代理是Java语言提供的一种在运行时创建代理对象的技术,它允许我们为已存在的接口创建代理类,以便在调用方法时添加额外的功能或控制。动态代理在很多场景下非常有用,比如日志记录、性能监控、事务管理等。...
Java动态代理机制是Java语言提供的一种强大的功能,它允许在运行时创建代理对象来实现特定接口,从而可以灵活地扩展或增强已有代码的功能。在Java中,动态代理主要通过两个类来实现:`java.lang.reflect.Proxy` 和 `...
### Java动态代理实现AOP详解 #### 一、引言 随着软件开发复杂度的提升,传统的面向对象编程(OOP)已经难以满足现代软件工程的需求。为了更好地管理跨切面的关注点,如日志记录、性能监控、安全控制等,面向切面...
java动态代理 public class HireProxy implements InvocationHandler { //被代理的真实角色 private Object obj; public HireProxy(Object obj) { super(); this.obj = obj; } //第二个参数method,被...
Java动态代理是Java提供的一种在运行时创建代理对象的技术,主要由`java.lang.reflect.Proxy`类和`java.lang.reflect.InvocationHandler`接口组成。在这个简单的Java动态代理实例中,我们将探讨如何利用这两个核心...
Java动态代理机制是Java语言提供的一种强大的功能,它允许在运行时创建代理对象来实现指定的接口。这一机制使得我们可以在不修改已有代码的情况下,为已有接口增加额外的功能或者增强已有功能的行为。在Java中,动态...
Java动态代理机制的优点在于灵活性和便捷性,它允许在运行时动态创建符合特定接口的代理对象,无需对原有代码做任何修改,使得我们可以方便地实现诸如日志、事务控制等跨切面的逻辑。不过,动态代理仅限于代理接口,...
Java动态代理实现AOP Java动态代理是实现Aspect Oriented Programming(AOP)的重要手段。在Java中,动态代理可以通过java.lang.reflect InvocationHandler接口和java.lang.reflect.Proxy类来实现。AOP的主要思想...
### Java动态代理知识点详解 #### 一、Java动态代理简介 在Java中,动态代理是一种非常重要的机制,它允许我们在运行时动态地创建一个接口的实现类实例。这种技术广泛应用于AOP(面向切面编程)、RPC(远程过程...
Java动态代理是Java编程中一个非常重要的特性,它允许我们在运行时创建代理对象来代替目标对象,以便在不修改原有代码的情况下对目标对象的行为进行增强或扩展。在Java.lang.reflect包下,动态代理主要涉及两个核心...
对代理模式与Java动态代理类的理解说明
总之,基于Java动态代理和反射机制实现ORM,可以有效地解耦业务逻辑和数据库操作,提高代码的可读性和可维护性。虽然现有的ORM框架如Hibernate、MyBatis已经相当成熟,但对于学习和理解Java的高级特性,这样的实践...
Java动态代理是Java语言提供的一种机制,它允许在运行时创建一个对象的代理,这个代理对象可以在调用实际方法之前和之后添加额外的功能。在Java中,动态代理主要通过`java.lang.reflect.Proxy`类和`java.lang....