Java 动态代理(proxy、invocationHandler)

本文深入探讨Java动态代理机制及其核心组件InvocationHandler的作用,解释如何创建动态代理类及其实现过程,包括代理类的生成、调用转发机制以及在实际应用中的常见场景。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

首先要明白代理是一种设计模式:


代理指代理某个对象,代理者通常与其代理的对象拥有相同的接口,调用者与代理进行交互,代理对调用者完全透明(调用者以为是调用这个实际的对象),调用者只关心接口并不关心怎么实现。


其目的就是提供一个代理以控制对某个对象(被代理者)的访问

 当通过使用代理(代理实现InvocationHandler接口)调用某个方法时,会自动调用代理的invoke方法,相当于拦截机制。因此可以在代理中封装逻辑,比如访问控制、远程通信、日志、缓存等等



首先要明白其中的概念:

**Handler: 处理者。处理业务逻辑等事情。

**Proxy:代理者。交给我来代理,我帮你管理事情,我出面去做本该你做的事情!我是抛头露面的侍者。

 

/*原接口,即将被委托给代理者*/
public interface MyInterface {
	public void execute();
}

 /*原接口实现*/
public class MyInterfaceImpl implements MyInterface {
	@Override
	public void execute() {
		System.out.println("execute() be called");
	}
}

创建代理:

//第一个参数是实现类的classloader,在运行时动态的加载实现类的.class对象。与普通的加载方式不同,不会在编译时加载.class
 (MyInterface) Proxy.newProxyInstance(
 myInterfaceImpl.getClass().getClassLoader(), 
 myInterfaceImpl.getClass().getInterfaces(),
 handler);



1.para1 被代理类(原接口实现)的类加载器 classLoader 
2.para2  被代理类 实现的所有接口 
3.para3 (传入了被代理类的 )处理者





 Proxy 静态方法生成动态代理类同样需要通过类装载器来进行装载才能使用,它与普通类的唯一区别就是其字节码是由 JVM 在运行时动态生成的而非预存在于任何一个 .class 文件中。

查看newProxyInstance源码:


public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)
			throws IllegalArgumentException {
		if (h == null) {
			throw new NullPointerException();
		}

		/*
		 * Look up or generate the designated proxy class.
		 * 
		 * 第一步:获得proxy.class
		 */
		Class<?> cl = getProxyClass0(loader, interfaces); // stack walk magic:
															// do not refactor

		/*
		 * Invoke its constructor with the designated invocation handler.
		 */
		try {// 第二步:获得这个proxy.class的构造器
		     // 第三部:通过这个构造器,创建实例对象,并返回
			final Constructor<?> cons = cl.getConstructor(constructorParams);
			final InvocationHandler ih = h;
			SecurityManager sm = System.getSecurityManager();
			if (sm != null && ProxyAccessHelper.needsNewInstanceCheck(cl)) {
				// create proxy instance with doPrivilege as the proxy class may
				// implement non-public interfaces that requires a special
				// permission
				return AccessController.doPrivileged(new PrivilegedAction<Object>() {
					public Object run() {
						return newInstance(cons, ih);
					}
				});
			} else {
				return newInstance(cons, ih);
			}
		} catch (NoSuchMethodException e) {
			throw new InternalError(e.toString());
		}
	}





这段代码运行后,代理产生,所有对代理的调用将被转发给handler,也就是转发给InvocationHandler接口的实现类。

 (---All method calls to the dynamic proxy are forwarded to thisInvocationHandler implementation)



import java.lang.reflect.Proxy;

public class Client {
	public static void main(String[] args) {
		// 我的接口实现 被代理对象
		MyInterface myInterfaceImpl = new MyInterfaceImpl();
		// InvocationHandler;把被代理者组合到InvocationHandler中,并且在invoke(拦截)方法中使用反射方式调用被代理者的方法
		BusinessHandler handler = new BusinessHandler(myInterfaceImpl);
		// 代理者 获得代理类($Proxy0 extends Proxy implements
		// MyInterface)的实例.在编译阶段,$Proxy0(代理类)class文件是没有加载到classLoader中的,
		// 而是在编译时期产生的(静态代理指编译器就产生这个代理class)。所以称为动态代理。
		// 1.第一个参数的RealSubject(被代理者)的classloader;
		// 2.第二个参数是RealSubject的所有父接口
		// 3.第三个参数是InvocationHandler
		MyInterface myInterfaceProxy = (MyInterface) Proxy.newProxyInstance(myInterfaceImpl.getClass().getClassLoader(),
				myInterfaceImpl.getClass().getInterfaces(), handler);
		myInterfaceProxy.execute();
	}
}




import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

/*InvocationHandler 处理者类*/
public class BusinessHandler implements InvocationHandler {
	private Object object = null;

	public BusinessHandler(Object object) {
		this.object = object;
	}

	/**
	 * 
	 * @param proxy  就是代理者, 一般没什么用
	 * @param method  代理者调用的方法,使用了反射机制,可以动态获取该方法的所有信息。
	 * @param args  被调用方法需要的参数(不需要则无所谓)
	 * **/
	@Override
	public Object invoke(Object proxy, Method method, Object[] args)
			throws Throwable {
		System.out.println("do something before method");

		Object ret = method.invoke(this.object, args);

		System.out.println("do something after method");
		return ret;
	}
}


参考链接:

http://tutorials.jenkov.com/java-reflection/dynamic-proxies.html     (反射)

http://hi.baidu.com/malecu/item/9e0edc115cb597a1feded5a0



评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值