代理模式--动态代理(CGLIB)

March . 04 . 2019
  • 前言

再来补充一个CGLIB的动态代理, JDK动态代理必须提供接口才能使用, 在一些不能提供接口的环境中, 只能采用其他第三方技术, 比如CGLIB。它的优势在于不需要提供接口, 只要一个非抽象类就能实现动态代理。

  • 包结构

捕获.JPG

  • 代码实现

Hello.java

package proxy.cg;

public class Hello {

    public void sayHello(String name)
    {
        System.out.println("Hello: " + name);
    }
}

CglibProxyExample.java

package proxy.cg;

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

import java.lang.reflect.Method;


public class CglibProxyExample implements MethodInterceptor {
    /**
     * 生成 CGLIB 代理对象
     * @param cls -- Class 类
     * @return Class 类的 CGLIB 代理对象
     */
    public Object getProxy(Class cls)
    {
        // CGLIB enhancer 增强类对象
        Enhancer enhancer = new Enhancer();
        // 设置增强类型
        enhancer.setSuperclass(cls);
        // 定义代理逻辑对象为当前对象, 要求当前对象实现 intercept 方法
        enhancer.setCallback(this);
        // 生成并返回代理对象
        return enhancer.create();
    }

    /**
     * 代理逻辑方法
     * @param o 代理对象
     * @param method 方法
     * @param args 方法参数
     * @param methodProxy 方法代理
     * @return 代理逻辑返回
     * @throws Throwable 异常
     */
    @Override
    public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {

        System.out.println("调用真实对象前");
        // CGLIB 反射调用真实对象方法
        Object result = methodProxy.invokeSuper(o, args);
        System.out.println("调用真实对象后");

        return result;
    }
}

这里使用了CGLIB的加强者 Enhancer, 通过设置超类(个人理解超类就是父类)的方法(setSuperclass), 然后通过 setCallback 方法设置那个类为它的代理类。 其中, 参数为 this 就意味着是当前对象, 实现 intercept 方法, 然后返回对象。

Test.java

package proxy.cg;

import net.sf.cglib.proxy.Enhancer;

public class Test {
    public static void main(String[] args)
    {
        Enhancer enhancer = new Enhancer();

        CglibProxyExample cg = new CglibProxyExample();
        Hello hello = (Hello) cg.getProxy(Hello.class);
        hello.sayHello("你好");
    }
}

  • 程序运行效果

2.JPG

  • 总结

不难发现JDK 的动态代理与 CGLIB 是很相似的, 它们都是通过 getProxy() 方法生成代理对象, 制定代理的逻辑类。 而代理逻辑类要实现一个接口的一个方法, 这个接口定义的方法就是代理对象的逻辑方法, 它可以控制真实对象的方法, skr~。