JDK动态代理的底层实现解析
JDK动态代理的底层实现解析
Java动态代理是一种在运行时创建代理和动态处理代理对象的机制。它能够在运行时生成代理类和对象,并将方法的调用转发到指定的处理器。
这种机制广泛应用于AOP(面向切面编程)等场景中,以实现对目标对象的增强和拓展。
实现原理
在Java中,动态代理的实现主要依赖于 java.lang.reflect.Proxy
类和 java.lang.reflect.InvocationHandler
接口。
接口与实现类
首先,我们定义一个接口 UserService
和其实现类 UserServiceImpl
,如下所示:
// 接口
interface UserService {
void addUser(String name);
void delUser(String name);
}
// 实现类
class UserServiceImpl implements UserService {
@Override
public void addUser(String name) {
System.out.printf("添加用户:%s", name);
}
@Override
public void delUser(String name) {
System.out.printf("删除用户:%s", name);
}
}
切面类
接着,我们创建一个切面类 UserLogger
,用于在目标方法执行前后进行一些操作:
// 切面类
class UserLogger {
public void before() {
System.out.println("---------------操作前");
}
public void after() {
System.out.println("---------------操作完成");
}
public void afterThrowing() {
System.out.println("---------------操作异常");
}
public void afterReturning() {
System.out.println("---------------操作结束");
}
}
JDK动态代理实现
在 JDKProxy
类中,我们实现 InvocationHandler
接口,用于处理代理实例的方法调用。在 createProxyInstance
方法中,我们通过 Proxy.newProxyInstance
创建代理对象:
// JDK动态代理的实现
class JDKProxy implements InvocationHandler {
private Object targetObject; //目标对象
public Object createProxyInstance(Object targetObject) {
this.targetObject = targetObject;
return Proxy.newProxyInstance(targetObject.getClass().getClassLoader(),
targetObject.getClass().getInterfaces(),
this);
}
public Object invoke(Object target, Method method, Object[] arg)
throws Throwable {
UserLogger userLogger = new UserLogger();//切面类
try {
//前置通知
userLogger.before();
// 调用目标方法
Object obj = method.invoke(targetObject, arg);// 切入点
userLogger.after();//后置通知
return obj;
} catch (RuntimeException e) {
e.printStackTrace();
userLogger.afterThrowing();//异常通知
} finally {
userLogger.afterReturning();//最终通知
}
return null;
}
}
在 invoke
方法中,我们通过反射调用目标对象的方法,并在方法调用前后添加切面逻辑。
示例
最后,在 Main
类中,我们演示如何使用动态代理来增强 UserService
接口的实现类:
// 示例
public class Main {
public static void main(String[] args) {
JDKProxy proxy = new JDKProxy();
UserService userService = (UserService) proxy.createProxyInstance(new UserServiceImpl());
userService.addUser("a");
userService.delUser("a");
}
}
通过运行示例代码,我们可以看到在方法执行前后,切面逻辑会被正确地执行,从而实现对目标方法的增强和拓展。
以下是完整示例代码:
package com.example.demo;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
// 接口
interface UserService {
void addUser(String name);
void delUser(String name);
}
// 实现类
class UserServiceImpl implements UserService {
@Override
public void addUser(String name) {
System.out.printf("添加用户:%s", name);
}
@Override
public void delUser(String name) {
System.out.printf("删除用户:%s", name);
}
}
// 切面类
class UserLogger {
public void before() {
System.out.println("---------------操作前");
}
public void after() {
System.out.println("---------------操作完成");
}
public void afterThrowing() {
System.out.println("---------------操作异常");
}
public void afterReturning() {
System.out.println("---------------操作结束");
}
}
// JDK动态代理的实现
class JDKProxy implements InvocationHandler {
private Object targetObject; //目标对象
public Object createProxyInstance(Object targetObject) {
this.targetObject = targetObject;
return Proxy.newProxyInstance(targetObject.getClass().getClassLoader(),
targetObject.getClass().getInterfaces(),
this);
}
public Object invoke(Object target, Method method, Object[] arg)
throws Throwable {
UserLogger userLogger = new UserLogger();//切面类
try {
//前置通知
userLogger.before();
// 调用目标方法
Object obj = method.invoke(targetObject, arg);// 切入点
userLogger.after();//后置通知
return obj;
} catch (RuntimeException e) {
e.printStackTrace();
userLogger.afterThrowing();//异常通知
} finally {
userLogger.afterReturning();//最终通知
}
return null;
}
}
// 示例
public class Main {
public static void main(String[] args) {
JDKProxy proxy = new JDKProxy();
UserService userService = (UserService) proxy.createProxyInstance(new UserServiceImpl());
userService.addUser("a");
userService.delUser("a");
}
}