Java进阶——静态代理与动态代理

发布于:2025-04-01 ⋅ 阅读:(18) ⋅ 点赞:(0)

        代理模式是一种常用的设计模式,为其他对象提供一种代理以控制对这个对象的访问。代理模式就像是一个中间人,客户端通过代理来间接访问目标对象,可以在不修改目标对象的基础上,对目标对象的功能进行增强或扩展。代理模式主要分为静态代理和动态代理,本文将详细探讨这两种代理模式。

一、静态代理

静态代理是指在编译时就已经确定代理类和目标类的关系。代理类和目标类都需要实现相同的接口,代理类中持有目标类的引用,在代理类的方法中调用目标类的相应方法,并可以在调用前后添加额外的逻辑。

1. 代码实现

// 定义接口
interface UserService {
    void addUser();
    void deleteUser();
}

// 实现类
class UserServiceImpl implements UserService {
    @Override
    public void addUser() {
        System.out.println("添加用户");
    }

    @Override
    public void deleteUser() {
        System.out.println("删除用户");
    }
}

// 静态代理类
class UserServiceProxy implements UserService {
    private UserService target;

    public UserServiceProxy(UserService target) {
        this.target = target;
    }

    @Override
    public void addUser() {
        System.out.println("添加用户前的日志记录");
        target.addUser();
        System.out.println("添加用户后的日志记录");
    }

    @Override
    public void deleteUser() {
        System.out.println("删除用户前的日志记录");
        target.deleteUser();
        System.out.println("删除用户后的日志记录");
    }
}


public class StaticProxy {
    public static void main(String[] args) {
        UserService target = new UserServiceImpl();
        UserService proxy = new UserServiceProxy(target);
        proxy.addUser();
        System.out.println("-------------------");
        proxy.deleteUser();
    }
}

在代理类的方法中,调用目标对象的方法前后添加了日志记录的逻辑

2. 优缺点

  • 优点:实现简单,易于理解,在编译时就可以确定代理关系,性能相对较高。
  • 缺点:代理类和目标类必须实现相同的接口,当接口方法发生变化时,代理类和目标类都需要修改。而且如果需要代理多个不同的目标类,就需要为每个目标类创建一个对应的代理类,代码会变得冗余。



二、动态代理

动态代理是指在运行时动态生成代理类,而不需要在编译时就确定代理类的代码。Java提供了两种实现动态代理的方式:JDK 动态代理和 CGLIB 动态代理。

1. JDK动态代理实现

JDK 动态代理是基于接口的动态代理,它使用 java.lang.reflect.Proxy 类和 java.lang.reflect.InvocationHandler 接口来实现。

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

interface UserService {
    void addUser();
    void deleteUser();
}

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

    @Override
    public void deleteUser() {
        System.out.println("删除用户");
    }
}

// 自定义InvocationHandler
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() + " 方法调用前的日志记录");
        Object result = method.invoke(target, args);
        System.out.println(method.getName() + " 方法调用后的日志记录");
        return result;
    }
}


public class JdkDynamicProxy {
    public static void main(String[] args) {
        UserService target = new UserServiceImpl();
        MyInvocationHandler handler = new MyInvocationHandler(target);
        UserService proxy = (UserService) Proxy.newProxyInstance(
                target.getClass().getClassLoader(),
                target.getClass().getInterfaces(),
                handler
        );
        proxy.addUser();
        System.out.println("-------------------");
        proxy.deleteUser();
    }
}

这种方式不需要为每个目标类创建代理类,只需要实现 InvocationHandler 接口,就可以为多个目标类提供代理服务。只能代理实现了接口的类,不能代理没有实现接口的类。

2. CGLIB动态代理

CGLIB 动态代理是基于继承的动态代理,可以代理没有实现接口的类。CGLIB是一个强大的、高性能的代码生成库,通过继承目标类来生成代理类。

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

import java.lang.reflect.Method;

// 目标类
class UserService {
    public void addUser() {
        System.out.println("添加用户");
    }

    public void deleteUser() {
        System.out.println("删除用户");
    }
}

// 自定义MethodInterceptor
class MyMethodInterceptor implements MethodInterceptor {
    @Override
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
        System.out.println(method.getName() + " 方法调用前的日志记录");
        Object result = proxy.invokeSuper(obj, args);
        System.out.println(method.getName() + " 方法调用后的日志记录");
        return result;
    }
}


public class CglibDynamicProxy {
    public static void main(String[] args) {
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(UserService.class);
        enhancer.setCallback(new MyMethodInterceptor());
        UserService proxy = (UserService) enhancer.create();
        proxy.addUser();
        System.out.println("-------------------");
        proxy.deleteUser();
    }
}

可以代理没有实现接口的类,灵活性更高,但是由于是基于继承实现的,所以不能代理 final 类和 final 方法。



← 上一篇 Java进阶——常用类及常用方法详解
记得点赞、关注、收藏哦!
下一篇 Java进阶——数组超详细整理 →