返回

大招聚齐,代理之道无处不在之静态代理、动态代理、cglib动态代理

后端

深度探究代理模式之精髓

代理模式是一种设计模式,允许您创建一个代表另一个对象的类。代理可以拦截并控制对原对象的访问,在不改变原对象自身的情况下,为原对象提供额外的功能或行为。

静态代理:简便易用,适时相伴

静态代理通过实现目标对象的接口,创建一个代理对象来代替原对象。代理对象与原对象之间存在一对一的对应关系。

优点:

  • 实现简单,结构清晰,易于理解和维护。

缺点:

  • 需要为每个原对象创建代理对象,代码量会增加。
  • 代理对象与原对象紧密耦合,当原对象发生变化时,代理对象也需要相应地修改。

JDK动态代理:灵活多变,游刃有余

JDK动态代理是一种通过反射机制创建代理对象的动态代理技术。它无需实现目标对象的接口,而是通过反射机制创建代理对象,并使用InvocationHandler接口来控制对原对象的调用。

优点:

  • 无需实现目标对象的接口,更加灵活。
  • 代理对象与原对象松散耦合,当原对象发生变化时,代理对象无需修改。
  • 支持对接口和类的代理。

缺点:

  • 性能开销比静态代理更大。
  • 只能代理接口,不能代理类。

Cglib动态代理:以类为本,无拘无束

Cglib动态代理是一种基于字节码生成技术的动态代理技术。它无需实现目标对象的接口,而是通过字节码生成技术创建一个代理类,并使用MethodInterceptor接口来控制对原对象的方法调用。

优点:

  • 可以代理类,也可以代理接口。
  • 性能开销比JDK动态代理更小。

缺点:

  • 实现更复杂,学习难度更大。
  • 不支持对final类和方法的代理。

三种代理模式之适用场景

  • 静态代理: 适用于原对象不需要频繁变化,代理对象与原对象紧密耦合的情况。
  • JDK动态代理: 适用于原对象需要频繁变化,代理对象与原对象松散耦合的情况。
  • Cglib动态代理: 适用于需要对类进行代理的情况,或需要更高性能的代理的情况。

技术指南:代码示例与实践指导

静态代理代码示例:

public class StaticProxy implements Subject {

    private Subject realSubject;

    public StaticProxy(Subject realSubject) {
        this.realSubject = realSubject;
    }

    @Override
    public void request() {
        System.out.println("Before request.");
        realSubject.request();
        System.out.println("After request.");
    }
}

public class Client {

    public static void main(String[] args) {
        Subject realSubject = new RealSubject();
        Subject proxy = new StaticProxy(realSubject);
        proxy.request();
    }
}

JDK动态代理代码示例:

public class JdkDynamicProxy implements InvocationHandler {

    private Subject subject;

    public JdkDynamicProxy(Subject subject) {
        this.subject = subject;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("Before request.");
        Object result = method.invoke(subject, args);
        System.out.println("After request.");
        return result;
    }

    public static void main(String[] args) {
        Subject realSubject = new RealSubject();
        Subject proxy = (Subject) Proxy.newProxyInstance(realSubject.getClass().getClassLoader(), realSubject.getClass().getInterfaces(), new JdkDynamicProxy(realSubject));
        proxy.request();
    }
}

Cglib动态代理代码示例:

public class CglibDynamicProxy implements MethodInterceptor {

    private Object targetObject;

    public CglibDynamicProxy(Object targetObject) {
        this.targetObject = targetObject;
    }

    @Override
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
        System.out.println("Before request.");
        Object result = method.invoke(targetObject, args);
        System.out.println("After request.");
        return result;
    }

    public static void main(String[] args) {
        RealSubject targetObject = new RealSubject();
        CglibDynamicProxy proxy = new CglibDynamicProxy(targetObject);
        Subject proxyObject = (Subject) Enhancer.create(targetObject.getClass(), proxy);
        proxyObject.request();
    }
}