JDK之动态代理(JDK与CGLIB)与静态代理

简介: 代理类在程序运行时创建的代理方式被称为动态代理静态代理中,代理类是自己定义好的,在程序运行之前就已经编译完成。然而动态代理,代理类并不是在Java代码中定义的,而是运行时根据我们在Java代码中的指示动态生成的。相比较静态代理,动态代理的优势在于可以很方便的对代理类的函数进行统一的处理,而不用修改每个代理类中的方法,比如想要在每个代理方法前都加上一个处理方法,静态代理就需要在每个类内部加上这个方法

动态代理


代理类在程序运行时创建的代理方式被称为动态代理

静态代理中,代理类是自己定义好的,在程序运行之前就已经编译完成。然而动态代理,代理类并不是在Java代码中定义的,而是运行时根据我们在Java代码中的指示动态生成的。相比较静态代理,动态代理的优势在于可以很方便的对代理类的函数进行统一的处理,而不用修改每个代理类中的方法,比如想要在每个代理方法前都加上一个处理方法,静态代理就需要在每个类内部加上这个方法


静态代理与动态代理的区别

静态代理

优点

简单、效率高、容易理解

缺点

当目标类增多,代理类也需要增加

当接口方法增加或修改的时候,很多类都需要修改,因为目标类和代理类都实现了相同的接口

动态代理

优点

动态代理中的目标类很多的时候代理类的数量可以很少

修改接口的方法的时候不会影响到代理类

代理类可以自动帮助我们生成无需手动


JDK动态代理


JDK动态代理是基于反射机制,生成一个实现代理接口的匿名类,然后重写方法进行方法增强。在调用具体方法前通过调用InvokeHandler的invoke方法来处理。

他的特点是生成代理类的速度很快,但是运行时调用方法操作会比较慢,因为是基于反射机制的,而且只能针对接口编程,即目标对象要实现接口

public interface Person {
    void sayHi();
}
public class Student implements Person{
    @Override
    public void sayHi() {
        System.out.println("Hi 我是一名学生");
    }
}
public class JDKProxy implements InvocationHandler {
    Object target;
    public Object newProxy(Object obj){
        this.target = obj;
        return Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(),this);
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("你好");
        Object invoke = method.invoke(target, args);
        System.out.println("再见");
        return invoke;
    }
}
public class JDKTest {
    public static void main(String[] args) {
        Person proxy = (Person) new JDKProxy().newProxy(new Student());
        proxy.sayHi();
    }
}

a005188a94fc450892ddf3c0d5592a00.png


CGLIB动态代理


Cglib(Code Generation Library)是一个强大的,高性能,高质量的Code生成类库,它是开源的。动态代理是利用 asm 开源包,将目标对象类的 class 文件加载进来,然后修改其字节码生成新的子类来进行扩展处理

    <--引入依赖-->
        <dependency>
            <groupId>cglib</groupId>
            <artifactId>cglib</artifactId>
            <version>3.3.0</version>
        </dependency>
public class Student {
    public void sayHi(){
        System.out.println("Hi 我是一名学生");
    }
}
public class CglibProxy implements MethodInterceptor {
    private Object target;
    public Object newProxy(Object target){
        this.target = target;
        // 增强器
        Enhancer enhancer = new Enhancer();
        enhancer.setCallback(this);
        enhancer.setSuperclass(target.getClass());
        return enhancer.create();
    }
    /**
     *
     * @param o 生成代理类的实例
     * @param method 上文实体类所调用的被代理的方法引用
     * @param objects 方法列表参数
     * @param methodProxy 生成代理类对方法的引用
     * @return
     * @throws Throwable
     */
    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        System.out.println("你好");
        Object invoke = methodProxy.invoke(target, objects);
        System.out.println("再见");
        return invoke;
    }
}
public class CglibTest {
    public static void main(String[] args) {
        CglibProxy proxy = new CglibProxy();
        Student student = (Student) proxy.newProxy(new Student());
        student.sayHi();
    }
}

e07ec90cf73f4847bbe26f4a60429c2e.png


两种代理方式的区别


JDK动态代理是基于反射机制,生成一个实现了接口继承了proxy类的匿名类而Cglib动态代理是基于继承机制,继承被代理类,底层是基于asm第三方框架对代理对象类的class文件加载进来,通过修改其字节码生成子类来处理

JDK动态代理生成类的速度快,后续执行类的方法操作慢而Cglib代理是生成类的速度慢,后续执行类的方法操作快


为什么JDK生成快,执行慢而Cglib与之相反


JDK动态代理通过会拦截方法,通过反射获取模板接口名字、内部方法以及参数,拼接生成一个新的Java代理对象

生成的代理对象不能直接调用被代理对象的方法,而是通过反射所有每次都得用反射调用一次所以执行方法都需要通过反射


Cglib代理实际上通过继承,生成一个子类,就是将代理对象类的class文件加载进来,通过修改其字节码生成子类来处理,生成类的速度慢但是后续执行时候就很快


相关文章
|
9月前
|
Java Spring
JDK动态代理和CGLIB动态代理的区别
Spring AOP中的动态代理主要有两种方式,JDK动态代理和CGLIB动态代理: ● JDK动态代理只提供接口的代理,不支持类的代理Proxy.newProxyInstance(类加载器, 代理对象实现的所有接口, 代理执行器) ● CGLIB是通过继承的方式做的动态代理 , 如果某个类被标记为final,那么它是无法使用 CGLIB做动态代理的。Enhancer.create(父类的字节码对象, 代理执行器)
|
9月前
|
监控 Java API
JDK动态代理和CGLIB动态代理
Java动态代理允许在运行时创建代理对象,增强或拦截目标类方法的执行。主要通过两种方式实现:JDK动态代理和CGLIB动态代理。JDK动态代理基于接口,利用`java.lang.reflect.Proxy`类和`InvocationHandler`接口;CGLIB则通过字节码技术生成目标类的子类作为代理,适用于未实现接口的类。两者均用于在方法执行前后添加额外逻辑,如日志记录、权限控制等,广泛应用于AOP框架中。
320 2
|
10月前
|
监控 Java API
JDK动态代理和CGLIB动态代理
Java动态代理允许在运行时创建代理对象,增强或拦截目标类的方法调用,无需修改原代码。它有两种主要实现方式:JDK动态代理和CGLIB动态代理。 - **JDK动态代理**:通过`java.lang.reflect.Proxy`类和`InvocationHandler`接口实现,适用于实现了接口的类。它在方法调用前后插入额外逻辑,如日志记录、权限控制等。 - **CGLIB动态代理**:基于字节码技术,为未实现接口的类生成子类作为代理,重写父类方法以添加增强逻辑。适用于没有接口的类,但要求目标类不能是`final`类或方法。
139 1
|
10月前
|
Java API 数据安全/隐私保护
探索Java动态代理的奥秘:JDK vs CGLIB
动态代理是一种在 运行时动态生成代理类的技术,无需手动编写代理类代码。它通过拦截目标方法的调用,实现对核心逻辑的 无侵入式增强(如日志、事务、权限控制等)。
312 0
探索Java动态代理的奥秘:JDK vs CGLIB
安装JDK18没有JRE环境的解决办法
安装JDK18没有JRE环境的解决办法
1294 141
|
5月前
|
存储 Ubuntu 安全
在Ubuntu 16.04上安装openjdk-6/7/8-jdk的步骤
在整个安装过程中,你可能需要管理员权限,因此你可能要使用 `sudo` 来获取必要的权限。记得做完每一个步骤后,都要检查输出,以确保没有发生错误,并且每项操作都成功完成。如果在安装过程中遇到问题,查看 `/var/log/` 下的日志文件对于问题的解决可能是有帮助的。
326 21
|
5月前
|
IDE Ubuntu Java
在Ubuntu18.04安装兼容JDK 8的Eclipse集成开发环境的指南。
完成以上步骤后,您将在Ubuntu 18.04系统上成功安装并配置了Eclipse IDE,它将与JDK 8兼容,可以开始进行Java开发工作。如果遇到任何问题,请确保每一步骤都正确执行,并检查是否所有路径都与您的具体情况相匹配。
220 11
|
4月前
|
Ubuntu Java Android开发
在Ubuntu 18.04上安装与JDK 8兼容的Eclipse版本的步骤。
安装过程结束后,您就可以开始使用Eclipse来开发您的Java项目了,并且确保它与JDK 8兼容无误。这个过程涉及的是一个基本的安装流程,针对使用Java 8的用户,Eclipse的其他配置和插件安装根据个人开发环境和需求来定制。
305 0
|
7月前
|
Java 关系型数据库 MySQL
在Linux平台上进行JDK、Tomcat、MySQL的安装并部署后端项目
现在,你可以通过访问http://Your_IP:Tomcat_Port/Your_Project访问你的项目了。如果一切顺利,你将看到那绚烂的胜利之光照耀在你的项目之上!
393 41
|
8月前
|
Oracle Java 关系型数据库
Tomcat和JDK的详细安装、下载和环境配置指南
以上就是JDK和Tomcat的下载、安装和环境配置的详细步骤。希望这个指南能帮助你顺利完成设置。
533 32