万字解读Java的动态代理

在Java中,动态代理是一种在运行时创建代理对象的技术。在许多场景中,动态代理能够极大地简化代码的编写,并且增强系统的灵活性和可扩展性。Java的动态代理主要有两种实现方式:JDK原生动态代理和CGLIB动态代理。本文将对这两种实现方式进行详细解读,并给出代码示例。

一、JDK原生动态代理

JDK的动态代理主要依赖于java.lang.reflect.Proxy类和InvocationHandler接口。它要求被代理的类实现一个或多个接口。

1. 创建接口和实现类

首先,我们定义一个接口和实现类:

public interface UserService {
    void addUser(String username);
}

public class UserServiceImpl implements UserService {
    @Override
    public void addUser(String username) {
        System.out.println("用户 " + username + " 被添加了");
    }
}

2. 创建InvocationHandler

我们需要一个InvocationHandler来处理代理对象的调用:

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

public class MyInvocationHandler implements InvocationHandler {
    private Object target;

    public MyInvocationHandler(Object target) {
        this.target = target;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("方法 " + method.getName() + " 被调用");
        return method.invoke(target, args);
    }
}

3. 创建代理对象

使用Proxy.newProxyInstance方法来创建动态代理对象:

import java.lang.reflect.Proxy;

public class DynamicProxyTest {
    public static void main(String[] args) {
        UserService userService = new UserServiceImpl();
        MyInvocationHandler handler = new MyInvocationHandler(userService);

        UserService proxyInstance = (UserService) Proxy.newProxyInstance(
                userService.getClass().getClassLoader(),
                userService.getClass().getInterfaces(),
                handler);

        proxyInstance.addUser("张三");
    }
}

4. 运行结果

运行上面的代码,输出如下:

方法 addUser 被调用
用户 张三 被添加了

二、CGLIB动态代理

CGLIB(Code Generation Library)是一个功能强大的高效的代码生成库,它可以在运行时动态生成某个类的子类,从而实现代理。与JDK的动态代理不同,CGLIB不需要被代理的类实现任何接口。

1. 创建目标类

我们定义一个普通类而非接口:

public class OrderService {
    public void createOrder(String orderName) {
        System.out.println("订单 " + orderName + " 被创建了");
    }
}

2. 创建MethodInterceptor

我们需要实现MethodInterceptor接口:

import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.Enhancer;

public class MyMethodInterceptor implements MethodInterceptor {
    @Override
    public Object intercept(Object obj, java.lang.reflect.Method method, Object[] args, 
                            net.sf.cglib.proxy.MethodProxy proxy) throws Throwable {
        System.out.println("方法 " + method.getName() + " 被调用");
        return proxy.invokeSuper(obj, args);
    }

    public static void main(String[] args) {
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(OrderService.class);
        enhancer.setCallback(new MyMethodInterceptor());

        OrderService proxyInstance = (OrderService) enhancer.create();
        proxyInstance.createOrder("订单1");
    }
}

3. 运行结果

运行代码,将输出:

方法 createOrder 被调用
订单 订单1 被创建了

三、总结

在这篇文章中,我们深入探讨了Java的动态代理,包括JDK原生动态代理和CGLIB动态代理的实现方式与示例代码。JDK动态代理更为常用,但受到限制,只能代理实现了接口的类。而CGLIB则没有这个限制,能够代理任何类型的类,通常比JDK动态代理执行速度快,但也因此引入了更多内存消耗。

选择使用哪种动态代理方式,通常取决于具体的使用场景及需求。希望通过本文的讲解,读者能够对Java的动态代理有更深的理解。

点赞(0) 打赏

微信小程序

微信扫一扫体验

微信公众账号

微信扫一扫加关注

发表
评论
返回
顶部