Skip to content

静态代理与动态代理的区别

字数
1045 字
阅读时间
5 分钟

[!summary]

  • 静态代理通过手动创建的代理类,在方法调用的前后添加额外的操作,但每个类都需要单独编写代理类,增加了重复劳动。
  • 动态代理则通过反射机制在运行时创建代理类,灵活性高,不需要为每个类编写代理,但使用反射可能会影响性能,调试也稍微复杂。

两种代理方式各有优缺点,具体使用时可以根据实际需求选择合适的方式。

静态代理动态代理的主要区别在于代理类的生成方式、灵活性以及实现的复杂程度:

  1. 静态代理

    • 定义:代理类在编译期就已经存在,必须由开发者手动编写或通过工具生成。代理类直接依赖于真实类。
    • 优点:实现简单,容易理解。
    • 缺点:需要为每个被代理的类单独编写代理类,增加代码量,灵活性较低。
  2. 动态代理

    • 定义:代理类在程序运行时动态生成,不需要开发者显式定义代理类。通过反射机制实现代理,能够在运行时灵活调用方法。
    • 优点:减少重复代码,灵活性高。可以应用于多个接口,不需要单独为每个服务编写代理类。
    • 缺点:基于反射机制,性能可能稍微低于静态代理,调试难度较大。

1 静态代理示例

1.1 接口定义

java
// 服务接口
public interface Service {
    void serve();
}

1.2 真实服务类

java
// 真实服务类
public class RealService implements Service {
    @Override
    public void serve() {
        System.out.println("真实服务处理请求");
    }
}

1.3 静态代理类

java
// 代理类
public class ServiceProxy implements Service {

    private Service realService;

    // 构造函数,传入真实服务对象
    public ServiceProxy(Service realService) {
        this.realService = realService;
    }

    @Override
    public void serve() {
        // 调用真实方法前的操作
        System.out.println("代理:方法调用前执行操作");

        // 调用真实服务对象的方法
        realService.serve();

        // 调用真实方法后的操作
        System.out.println("代理:方法调用后执行操作");
    }
}

1.4 静态代理使用

java
public class StaticProxyDemo {
    public static void main(String[] args) {
        // 创建真实服务对象
        Service realService = new RealService();

        // 创建代理对象,并将真实对象传递给代理对象
        Service proxy = new ServiceProxy(realService);

        // 通过代理对象调用方法
        proxy.serve();
    }
}

1.5 输出结果

代理:方法调用前执行操作
真实服务处理请求
代理:方法调用后执行操作

2 动态代理示例

2.1 接口定义

java
// 服务接口
public interface Service {
    void serve();
}

2.2 真实服务类

java
// 真实服务类
public class RealService implements Service {
    @Override
    public void serve() {
        System.out.println("真实服务处理请求");
    }
}

2.3 动态代理处理类

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

// 动态代理处理类
public class ServiceInvocationHandler implements InvocationHandler {

    private Object target;

    // 构造函数,传入真实对象
    public ServiceInvocationHandler(Object target) {
        this.target = target;
    }

    // 处理方法调用
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        // 在调用真实方法前添加一些操作
        System.out.println("代理:方法调用前执行操作");

        // 调用真实对象的方法
        Object result = method.invoke(target, args);

        // 在调用真实方法后添加一些操作
        System.out.println("代理:方法调用后执行操作");

        return result;
    }
}

2.4 动态代理使用

java
import java.lang.reflect.Proxy;

public class DynamicProxyDemo {
    public static void main(String[] args) {
        // 创建真实对象
        Service realService = new RealService();

        // 创建动态代理
        Service proxyService = (Service) Proxy.newProxyInstance(
            realService.getClass().getClassLoader(),
            realService.getClass().getInterfaces(),
            new ServiceInvocationHandler(realService)
        );

        // 调用代理对象的方法
        proxyService.serve();
    }
}

2.5 输出结果

代理:方法调用前执行操作
真实服务处理请求
代理:方法调用后执行操作