返回

Java基础-探寻cglib动态代理的本质

见解分享

cglib动态代理的本质

cglib动态代理与JDK动态代理相似,都采用了字节码技术,通过生成新的字节码实现对目标类的增强。cglib动态代理是通过修改目标类的字节码生成新的子类,从而实现动态代理。这种方式不需要实现接口,因此适用范围更广。

cglib动态代理与JDK动态代理的比较

特性 cglib动态代理 JDK动态代理
目标类要求 不需要实现接口 必须实现接口
代理方式 生成新的子类 实现接口
适用范围 更广 仅限于实现了接口的类
性能 较低 较高

cglib动态代理的应用场景

cglib动态代理广泛应用于以下场景:

  • 对没有实现接口的类进行动态代理
  • 需要对目标类进行更细粒度的控制
  • 需要提高代理的性能

实际应用案例

案例一:对没有实现接口的类进行动态代理

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

public class Main {

    public static void main(String[] args) {
        // 创建目标类对象
        Target target = new Target();

        // 创建Enhancer对象
        Enhancer enhancer = new Enhancer();

        // 设置目标类
        enhancer.setSuperclass(Target.class);

        // 设置方法拦截器
        enhancer.setCallback(new MethodInterceptor() {
            @Override
            public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
                // 在方法调用前后执行自定义逻辑
                System.out.println("方法调用前");
                Object result = proxy.invokeSuper(obj, args);
                System.out.println("方法调用后");
                return result;
            }
        });

        // 创建代理类对象
        Target proxy = (Target) enhancer.create();

        // 调用代理类的方法
        proxy.sayHello();
    }
}

class Target {
    public void sayHello() {
        System.out.println("Hello world!");
    }
}

案例二:对目标类进行更细粒度的控制

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

public class Main {

    public static void main(String[] args) {
        // 创建目标类对象
        Target target = new Target();

        // 创建Enhancer对象
        Enhancer enhancer = new Enhancer();

        // 设置目标类
        enhancer.setSuperclass(Target.class);

        // 设置方法拦截器
        enhancer.setCallback(new MethodInterceptor() {
            @Override
            public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
                // 根据方法名进行不同的处理
                if ("sayHello".equals(method.getName())) {
                    // 对sayHello方法进行增强
                    System.out.println("方法调用前");
                    Object result = proxy.invokeSuper(obj, args);
                    System.out.println("方法调用后");
                    return result;
                } else {
                    // 对其他方法不进行增强
                    return proxy.invokeSuper(obj, args);
                }
            }
        });

        // 创建代理类对象
        Target proxy = (Target) enhancer.create();

        // 调用代理类的方法
        proxy.sayHello();
        proxy.sayGoodbye();
    }
}

class Target {
    public void sayHello() {
        System.out.println("Hello world!");
    }

    public void sayGoodbye() {
        System.out.println("Goodbye world!");
    }
}

案例三:提高代理的性能

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

public class Main {

    public static void main(String[] args) {
        // 创建目标类对象
        Target target = new Target();

        // 创建Enhancer对象
        Enhancer enhancer = new Enhancer();

        // 设置目标类
        enhancer.setSuperclass(Target.class);

        // 设置方法拦截器
        enhancer.setCallback(new MethodInterceptor() {
            @Override
            public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
                // 缓存方法调用结果
                Map<String, Object> cache = new HashMap<>();
                String key = method.getName() + Arrays.toString(args);
                if (cache.containsKey(key)) {
                    // 从缓存中获取结果
                    return cache.get(key);
                } else {
                    // 调用目标类的方法并缓存结果
                    Object result = proxy.invokeSuper(obj, args);
                    cache.put(key, result);
                    return result;
                }
            }
        });

        // 创建代理类对象
        Target proxy = (Target) enhancer.create();

        // 调用代理类的方法
        proxy.sayHello();
        proxy.sayHello();
    }
}

class Target {
    public void sayHello() {
        System.out.println("Hello world!");
    }
}

总结

cglib动态代理是一种功能强大的动态代理技术,可以对目标类进行更细粒度的控制。cglib动态代理与JDK动态代理各有优缺点,在实际项目中应根据具体情况选择合适的动态代理技术。