c语言编程笔录

您现在的位置是:首页 > 编程 > 编程经验

编程经验

深入浅析java 中的JDK与cglib动态代理

陈婉璇 2023-07-10编程经验
什么是JDK动态代理?JDK动态代理是Java语言自带的一种动态代理,它可以在运行期间动态生成代理类和代理对象,无需手动编写代理类的Java文件。要使用JDK动态代理,需要

什么是JDK动态代理?

JDK动态代理是Java语言自带的一种动态代理,它可以在运行期间动态生成代理类和代理对象,无需手动编写代理类的Java文件。要使用JDK动态代理,需要目标类实现一个接口,并且需要一个实现InvocationHandler接口的代理类来实现具体的代理逻辑。

以下是一个简单的使用JDK动态代理的例子。假设有一个接口UserService,代理类MyInvocationHandler和目标类UserServiceImpl,我们通过JDK动态代理创建一个代理对象实例。


public interface UserService {
    void addUser();
}

public class UserServiceImpl implements UserService {
    @Override
    public void addUser() {
        System.out.println("add user");
    }
}

public class MyInvocationHandler implements InvocationHandler {
    private Object target;
    public MyInvocationHandler(Object target) {
        this.target = target;
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("before invoke");
        Object result = method.invoke(target, args);
        System.out.println("after invoke");
        return result;
    }
}

public class Test {
    public static void main(String[] args) {
        UserService userService = new UserServiceImpl();
        InvocationHandler invocationHandler = new MyInvocationHandler(userService);
        UserService proxy = (UserService) Proxy.newProxyInstance(UserService.class.getClassLoader(), new Class[]{UserService.class}, invocationHandler);
        proxy.addUser();
    }
}

什么是cglib动态代理?

cglib动态代理是一个利用字节码技术生成代理类的库,它能够代理没有实现接口的类。与JDK动态代理不同的是,cglib动态代理会继承目标类,所以目标类的方法不能被声明为final。

以下是一个简单的使用cglib动态代理的例子。假设有一个目标类UserServiceImpl,我们通过cglib动态代理创建一个代理对象实例。


public class UserServiceImpl {
    public void addUser() {
        System.out.println("add user");
    }
}

public class MyMethodInterceptor implements MethodInterceptor {
    @Override
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
        System.out.println("before invoke");
        Object result = proxy.invokeSuper(obj, args);
        System.out.println("after invoke");
        return result;
    }
}

public class Test {
    public static void main(String[] args) {
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(UserServiceImpl.class);
        enhancer.setCallback(new MyMethodInterceptor());
        UserServiceImpl proxy = (UserServiceImpl) enhancer.create();
        proxy.addUser();
    }
}

JDK动态代理和cglib动态代理的区别

1. JDK动态代理只能代理实现了接口的目标类,cglib动态代理可以代理没有实现接口的目标类。


public class NoInterfaceClass {
    public void myMethod() {
        System.out.println("my method");
    }
}

public class MyMethodInterceptor implements MethodInterceptor {
    @Override
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
        System.out.println("before invoke");
        Object result = proxy.invokeSuper(obj, args);
        System.out.println("after invoke");
        return result;
    }
}

public class Test {
    public static void main(String[] args) {
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(NoInterfaceClass.class);
        enhancer.setCallback(new MyMethodInterceptor());
        NoInterfaceClass proxy = (NoInterfaceClass) enhancer.create();
        proxy.myMethod();
    }
}

2. JDK动态代理生成的代理类是目标类实现的接口,cglib动态代理生成的代理类是目标类的子类。

3. JDK动态代理比cglib动态代理速度更快,但JDK动态代理只能代理实现了接口的目标类。

使用场景

JDK动态代理和cglib动态代理在不同的情况下有不同的使用场景。

JDK动态代理适用于需要代理实现了接口的目标类的场景,比如Spring中的AOP。由于JDK动态代理生成的代理类是实现了接口的类,所以它可以和原始类一起直接放入JVM中运行,不需要通过类加载器进行特殊处理,因此JDK动态代理生成的对象运行速度较快。

cglib动态代理适用于需要代理没有实现接口的目标类的场景。cglib动态代理可以为目标类生成一个子类,在子类中拦截目标方法并进行增强。由于cglib动态代理需要生成一个子类,所以它对目标类的访问是通过方法拦截实现的,因此cglib动态代理生成的对象运行速度相对较慢。

文章评论