`

Java动态代理

阅读更多
Java提供了动态代理,可以完成AOP和装饰模式的功能,主要的Proxy类和InvocationHandler接口:
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();
	}
}
分享到:
评论
1 楼 kuangfengkuang 2012-06-26  
zzzzz

相关推荐

    java动态代理demo

    Java动态代理是Java编程中一个重要的特性,它允许我们在运行时创建代理对象,这些代理对象可以代表并增强原对象的功能。动态代理在很多场景下都非常有用,比如日志记录、性能监控、事务管理等。本示例将带你深入理解...

    java动态代理实例

    Java动态代理是Java语言提供的一种在运行时创建代理对象的技术,它允许我们为已存在的接口创建代理类,以便在调用真实目标对象的方法时添加额外的功能或行为。在这个实例中,我们将深入探讨Java动态代理的核心概念,...

    java动态代理 经典文章(word 2007格式的)

    Java动态代理是Java编程中一个重要的特性,它允许在运行时创建代理对象,这些代理对象可以代表并增强原对象的功能。动态代理主要应用于面向切面编程(AOP)和事件监听等场景,使得代码更加模块化,易于维护。以下是...

    Java动态代理两种实现方式

    Java动态代理技术是Java编程中一个非常重要的特性,它允许我们在运行时动态创建具有特定行为的对象。这种技术常用于AOP(面向切面编程)和框架中,如Spring AOP,用于实现方法拦截、事务管理等功能。Java提供了两种...

    Java动态代理helloworld

    本篇文章将深入探讨Java动态代理的概念、原理以及如何通过一个简单的"Hello, World!"示例来理解它。 动态代理,顾名思义,是在程序运行时动态地生成代理对象。与静态代理(编译时已知)相比,动态代理更加灵活,...

    Java 动态代理详解(学习资料)

    JDK 动态代理JDK 提供了 java.lang.reflect.Proxy 类和 java.lang.reflect.InvocationHandler 接口来支持动态代理。Proxy 类用于创建一个代理对象,而 InvocationHandler 接口则定义了代理对象的方法调用处理逻辑。...

    java 动态代理 简单实例

    Java动态代理是Java语言提供的一种在运行时创建代理对象的技术,它允许我们为已存在的接口创建代理类,以便在调用方法时添加额外的功能或控制。动态代理在很多场景下非常有用,比如日志记录、性能监控、事务管理等。...

    java动态代理机制

    Java动态代理机制是Java语言提供的一种强大的功能,它允许在运行时创建代理对象来实现特定接口,从而可以灵活地扩展或增强已有代码的功能。在Java中,动态代理主要通过两个类来实现:`java.lang.reflect.Proxy` 和 `...

    java 动态代理实现AOP

    ### Java动态代理实现AOP详解 #### 一、引言 随着软件开发复杂度的提升,传统的面向对象编程(OOP)已经难以满足现代软件工程的需求。为了更好地管理跨切面的关注点,如日志记录、性能监控、安全控制等,面向切面...

    java动态代理和反射

    java动态代理 public class HireProxy implements InvocationHandler { //被代理的真实角色 private Object obj; public HireProxy(Object obj) { super(); this.obj = obj; } //第二个参数method,被...

    一个简单的java动态代理的实例

    Java动态代理是Java提供的一种在运行时创建代理对象的技术,主要由`java.lang.reflect.Proxy`类和`java.lang.reflect.InvocationHandler`接口组成。在这个简单的Java动态代理实例中,我们将探讨如何利用这两个核心...

    java动态代理(2)

    Java动态代理机制是Java语言提供的一种强大的功能,它允许在运行时创建代理对象来实现指定的接口。这一机制使得我们可以在不修改已有代码的情况下,为已有接口增加额外的功能或者增强已有功能的行为。在Java中,动态...

    java动态代理机制分析及拓展

    Java动态代理机制的优点在于灵活性和便捷性,它允许在运行时动态创建符合特定接口的代理对象,无需对原有代码做任何修改,使得我们可以方便地实现诸如日志、事务控制等跨切面的逻辑。不过,动态代理仅限于代理接口,...

    用Java动态代理实现AOP

    Java动态代理实现AOP Java动态代理是实现Aspect Oriented Programming(AOP)的重要手段。在Java中,动态代理可以通过java.lang.reflect InvocationHandler接口和java.lang.reflect.Proxy类来实现。AOP的主要思想...

    java动态代理

    ### Java动态代理知识点详解 #### 一、Java动态代理简介 在Java中,动态代理是一种非常重要的机制,它允许我们在运行时动态地创建一个接口的实现类实例。这种技术广泛应用于AOP(面向切面编程)、RPC(远程过程...

    java动态代理(3)

    Java动态代理是Java编程中一个非常重要的特性,它允许我们在运行时创建代理对象来代替目标对象,以便在不修改原有代码的情况下对目标对象的行为进行增强或扩展。在Java.lang.reflect包下,动态代理主要涉及两个核心...

    对代理模式与Java动态代理类的理解

    对代理模式与Java动态代理类的理解说明

    基于Java动态代理和反射机制实现ORM

    总之,基于Java动态代理和反射机制实现ORM,可以有效地解耦业务逻辑和数据库操作,提高代码的可读性和可维护性。虽然现有的ORM框架如Hibernate、MyBatis已经相当成熟,但对于学习和理解Java的高级特性,这样的实践...

    Java动态代理实现数据源连接池

    Java动态代理是Java语言提供的一种机制,它允许在运行时创建一个对象的代理,这个代理对象可以在调用实际方法之前和之后添加额外的功能。在Java中,动态代理主要通过`java.lang.reflect.Proxy`类和`java.lang....

Global site tag (gtag.js) - Google Analytics