代理模式

  1. 功能增强:在原有的功能上,增加了额外的功能,
  2. 控制访问:代理类不让你访问目标对象,只能通过代理对象来控制目标对象。

使用代理对象包装目标对象,每次访问目标对象时,都通过代理对象来访问。

代理对象就可以控制目标对象实现功能的过程,并且在其中添加额外的功能.

两个一致:

  1. 代理对象和目标对象 功能一致 :代理对象和目标对象实现相同的接口

  2. 结果一致 : 代理对象实现功能的过程,就是目标对象实现功能的过程。

静态代理

代理类是自己手动实现的,

目标类是确定好的。

  1. 核心功能前
  2. 核心功能后
  3. catch中
  4. finally中

动态代理

1. JDK动态代理 (Interface Proxy)

JDK动态代理主要依赖于java.lang.reflect.Proxy类和java.lang.reflect.InvocationHandler接口。JDK动态代理适用于那些实现了接口的类。

  • 实现原理

    • 利用反射机制在运行时动态地创建一个实现了给定接口列表的新类。
    • 这个新类将代理原始的对象,并且所有的方法调用都将被转发到一个实现了InvocationHandler接口的实例上。
    • InvocationHandlerinvoke方法会在每次代理对象的方法被调用时触发。
  • 示例代码

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    public interface MyInterface {
    void doSomething();
    }

    InvocationHandler handler = new InvocationHandler() {
    private final MyInterface target;

    public MyInterfaceHandler(MyInterface target) {
    this.target = target;
    }

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

    MyInterface myInterface = (MyInterface) Proxy.newProxyInstance(
    MyInterface.class.getClassLoader(),
    new Class<?>[]{MyInterface.class},
    handler
    );
  • 优点

    • 无需编写代理类的源代码。
    • 代理类在运行时生成,减少了编码工作量。
  • 缺点

    • 只能代理实现了接口的类。
    • 如果没有实现接口,则无法使用JDK动态代理。

2. CGLIB动态代理 (Subclass Proxy)

CGLIB(Code Generation Library)是一个强大的高性能的代码生成库,它使用ASM(字节码操作库)来动态生成代理类。

  • 实现原理

    • 通过字节码技术为一个类创建一个子类实例。
    • 这个子类重写了父类的所有非final方法,并且在方法前后添加额外的逻辑。
    • 使用Enhancer类来创建动态代理类。
  • 示例代码

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    import net.sf.cglib.proxy.Enhancer;
    import net.sf.cglib.proxy.MethodInterceptor;
    import net.sf.cglib.proxy.MethodProxy;

    public class MyClass {
    public void doSomething() {
    System.out.println("Doing something...");
    }
    }

    Enhancer enhancer = new Enhancer();
    enhancer.setSuperclass(MyClass.class);
    enhancer.setCallback(new MethodInterceptor() {
    @Override
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
    System.out.println("Before method call");
    Object result = proxy.invokeSuper(obj, args);
    System.out.println("After method call");
    return result;
    }
    });

    MyClass myClass = (MyClass) enhancer.create();
  • 优点

    • 不需要目标类实现接口。
    • 可以代理任意类,只要该类不是final的,且其方法不是final的。
  • 缺点

    • 生成的代理类比JDK动态代理要稍微慢一点。
    • 不能代理final类和final方法。