JDK是如何支持动态代理的?请简要说明其实现机制。
Java的动态代理主要基于java.lang.reflect.Proxy
类和java.lang.reflect.InvocationHandler
接口实现。这两个是JDK自带的API,不需要额外的依赖。
以下是概念和步骤:
- 接口InvocationHandler:它是动态代理的核心接口,定义了一个方法
invoke(Object proxy, Method method, Object[] args)
,当我们通过代理对象调用一个方法时,这个方法就会被执行。 -
类Proxy:它是所有动态代理类的父类,它有一个非常重要的方法
newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)
,这个方法返回一个实现了指定接口的代理对象。
动态代理的实现过程:
- 实现一个InvocationHandler接口,它定义了我们希望代理对象执行的操作。例如,我们可能希望在调用代理对象的方法前后打印日志。
public class LogInvocationHandler implements InvocationHandler { private Object target; public LogInvocationHandler(Object target) { this.target = target; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("Method " + method.getName() + " is invoked"); return method.invoke(target, args); } }
- 使用Proxy的静态方法
newProxyInstance
创建代理对象,传入的参数是我们的类加载器、我们希望代理的接口、以及我们定义的InvocationHandler。SomeService service = // create the actual service InvocationHandler handler = new LogInvocationHandler(service); SomeService proxyService = (SomeService) Proxy.newProxyInstance( SomeService.class.getClassLoader(), new Class<?>[] {SomeService.class}, handler );
在这个例子中,当我们调用proxyService
的方法时,实际上会调用LogInvocationHandler
的invoke
方法,实现了方法调用的拦截和额外的日志打印。
注意:JDK动态代理只能对接口进行代理,无法对类进行代理。如果需要对类进行代理,可以考虑使用CGLIB等工具。