jdk和cglib动态代理区别

原创admin 分类:热门问答 0

jdk和cglib动态代理区别

在Java的世界里,动态代理是一种强大的技术,它允许我们在运行时动态地创建对象的代理。这种技术在许多高级应用中都扮演着关键角色,比如AOP(面向切面编程)、事务管理、日志记录等。Java提供了两种主要的动态代理实现方式:JDK动态代理和CGLIB动态代理。本文将详细探讨这两种代理的区别、核心类与方法、使用场景,并提供代码案例以加深理解。

代理的基本概念与目的

动态代理的主要目的是在不修改原有对象代码的情况下,为其方法调用添加额外的行为。这可以通过在方法调用前后添加自定义逻辑来实现,比如权限检查、事务处理等。动态代理的使用者不需要关心代理对象的具体实现细节,只需要通过代理对象来调用目标对象的方法即可。

JDK动态代理与CGLIB动态代理的对比

核心类与方法

JDK动态代理

  • 核心类java.lang.reflect.Proxy
  • 核心方法newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)【1】
  • 特点:基于接口实现代理,要求目标对象必须实现至少一个接口【1】。

CGLIB动态代理

  • 核心类net.sf.cglib.proxy.Enhancer
  • 核心方法create(Class<?>[] interfaces, Object... callbacks)【2】【3】
  • 特点:基于子类继承实现代理,可以代理没有实现接口的类,甚至可以代理final类【2】【3】。

使用场景

JDK动态代理

  • 适用场景:当你的目标对象已经实现了一个或多个接口时,JDK动态代理是首选【3】。
  • 优势:简单易用,性能较高,因为是基于接口的代理,所以运行时性能损耗较小【3】。

CGLIB动态代理

  • 适用场景:当目标对象没有实现接口或者你需要代理的是具体类时,CGLIB动态代理是更好的选择【2】。
  • 优势:灵活性更高,可以代理没有实现接口的类,包括final类【2】。

代码案例

JDK动态代理案例

// 定义一个接口
interface IService {
    void serve();
}

// 实现类
class ServiceImpl implements IService {
    public void serve() {
        System.out.println("Service Implemented.");
    }
}

// 代理工厂
class ProxyFactory implements InvocationHandler {
    private IService target;

    public ProxyFactory(IService target) {
        this.target = target;
    }

    public IService getProxy() {
        return (IService) Proxy.newProxyInstance(
                target.getClass().getClassLoader(),
                new Class[]{IService.class},
                this
        );
    }

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

// 客户端使用
public class JDKProxyTest {
    public static void main(String[] args) {
        ServiceImpl service = new ServiceImpl();
        ProxyFactory factory = new ProxyFactory(service);
        IService proxyService = factory.getProxy();
        proxyService.serve(); // 输出:Before service call. Service Implemented. After service call.
    }
}

CGLIB动态代理案例

// 目标类
class RealSubject {
    public void request() {
        System.out.println("RealSubject Request.");
    }
}

// 代理类
class CglibProxy implements MethodInterceptor {
    private RealSubject realSubject;

    public CglibProxy(RealSubject realSubject) {
        this.realSubject = realSubject;
    }

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

// 客户端使用
public class CGLIBProxyTest {
    public static void main(String[] args) {
        RealSubject realSubject = new RealSubject();
        CglibProxy cglibProxy = new CglibProxy(realSubject);
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(realSubject.getClass());
        enhancer.setCallback(cglibProxy);
        RealSubject proxySubject = (RealSubject) enhancer.create();
        proxySubject.request(); // 输出:Before method call. RealSubject Request. After method call.
    }
}

总结

JDK动态代理和CGLIB动态代理都是Java中实现动态代理的重要技术。JDK动态代理适用于接口代理,简单且性能较高;而CGLIB动态代理则适用于类代理,提供了更高的灵活性。开发者应根据实际需求和目标对象的特性来选择合适的动态代理技术。通过本文提供的代码案例,我们可以更直观地理解这两种动态代理的使用方式和场景。在实际开发中,合理运用动态代理技术可以大大提高代码的可维护性和扩展性。

相关文章

猜你喜欢

领取相关Java架构师视频资料

网络安全学习平台视频资料