博客
关于我
Spring的两种动态代理:JDK动态代理和cglib动态代理
阅读量:239 次
发布时间:2019-02-28

本文共 3559 字,大约阅读时间需要 11 分钟。

JAVA动态代理与CGLIB动态代理的对比及实现

一、原理区别

JAVA动态代理基于反射机制,通过生成实现指定接口的匿名类来实现代理。而CGLIB动态代理则是基于ASM框架,对目标类的字节码进行修改或增强,生成一个继承自目标类的子类,从而实现代理功能。

1. 接口实现的处理方式

  • JDK动态代理:默认情况下,如果目标对象实现了接口,会采用JDK动态代理实现AOP。
  • CGLIB动态代理:即使目标对象实现了接口,也可以强制使用CGLIB实现AOP。

2. 无接口对象的处理

如果目标对象没有实现任何接口,Spring会自动选择CGLIB动态代理,因为JDK动态代理无法处理无接口的目标对象。

如何强制使用CGLIB实现AOP

  • 添加CGLIB库

    • 需要添加对应的JAR文件,例如spring-boot-dependencies.properties中添加asm-5.2.0.jarcglib-3.2.5.jar等。
  • 配置Spring

    • 在Spring配置文件中添加以下配置:
  • JDK动态代理与CGLIB动态代理的区别

    1. 适用场景

    • JDK动态代理:只能针对实现了接口的类生成代理。
    • CGLIB动态代理:可以针对任意类生成代理,通常用于处理无接口的目标对象。

    2. 生成方式

    • JDK动态代理:基于反射机制,动态生成接口实现类。
    • CGLIB动态代理:基于ASM框架,静态修改目标类字节码生成子类。

    3. 优缺点

    • JDK动态代理:实现简单,性能较好。但无法代理无接口的目标对象。
    • CGLIB动态代理:实现复杂,生成子类,适合处理无接口对象,但可能导致性能损失。

    二、代码实现

    用户管理接口

    package com.lf.shejimoshi.proxy.entity;public interface UserManager {    void addUser(String userName, String password);    void delUser(String userName);}

    用户管理实现类

    package com.lf.shejimoshi.proxy.entity;public class UserManagerImpl implements UserManager {    @Override    public void addUser(String userName, String password) {        System.out.println("调用了新增的方法!");        System.out.println("传入参数为 userName: " + userName + " password: " + password);    }    @Override    public void delUser(String userName) {        System.out.println("调用了删除的方法!");        System.out.println("传入参数为 userName: " + userName);    }}

    JDK动态代理实现

    package com.lf.shejimoshi.proxy.jdk;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;import java.lang.reflect.Proxy;import com.lf.shejimoshi.proxy.entity.UserManager;import com.lf.shejimoshi.proxy.entity.UserManagerImpl;public class JdkProxy implements InvocationHandler {    private Object target;    @Override    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {        System.out.println("JDK动态代理,监听开始!");        Object result = method.invoke(target, args);        System.out.println("JDK动态代理,监听结束!");        return result;    }    private Object getJDKProxy(Object targetObject) {        this.target = targetObject;        return Proxy.newProxyInstance(targetObject.getClass().getClassLoader(), targetObject.getClass().getInterfaces(), this);    }    public static void main(String[] args) {        JdkProxy jdkProxy = new JdkProxy();        UserManager user = (UserManager) jdkProxy.getJDKProxy(new UserManagerImpl());        user.addUser("admin", "123123");    }}

    CGLIB动态代理实现

    package com.lf.shejimoshi.proxy.cglib;import java.lang.reflect.Method;import com.lf.shejimoshi.proxy.entity.UserManager;import com.lf.shejimoshi.proxy.entity.UserManagerImpl;import net.sf.cglib.proxy.Enhancer;import net.sf.cglib.proxy.MethodInterceptor;import net.sf.cglib.proxy.MethodProxy;public class CglibProxy implements MethodInterceptor {    private Object target;    @Override    public Object intercept(Object obj, Method method, Object[] arr, MethodProxy proxy) throws Throwable {        System.out.println("Cglib动态代理,监听开始!");        Object invoke = method.invoke(target, arr);        System.out.println("Cglib动态代理,监听结束!");        return invoke;    }    public Object getCglibProxy(Object objectTarget) {        this.target = objectTarget;        Enhancer enhancer = new Enhancer();        enhancer.setSuperclass(objectTarget.getClass());        enhancer.setCallback(this);        return enhancer.create();    }    public static void main(String[] args) {        CglibProxy cglib = new CglibProxy();        UserManager user = (UserManager) cglib.getCglibProxy(new UserManagerImpl());        user.delUser("admin");    }}

    运行结果

    运行以上代码,您可以在控制台中观察到JDK动态代理和CGLIB动态代理的输出结果,分别显示了两种代理方式的工作流程。

    转载地址:http://juhs.baihongyu.com/

    你可能感兴趣的文章
    PHP对表单提交特殊字符的过滤和处理
    查看>>
    php对象引用和析构函数的关系
    查看>>
    RabbitMQ HTTP 认证后端项目常见问题解决方案
    查看>>
    PHP将图片转换成base64格式(优缺点)
    查看>>
    php将多个值的数组去除重复元素
    查看>>
    php局域网上传文件_PHP如何通过CURL上传文件
    查看>>
    PHP工具插件大全
    查看>>
    php布尔值的++
    查看>>
    PHP常量、变量作用域详解(一)
    查看>>
    PHP应用目录结构设计
    查看>>
    PHP应用程序连接MSQL数据库Demo(附crud程序)
    查看>>
    PHP开发api接口安全验证
    查看>>
    PHP开发规范PSR
    查看>>
    PHP开发遇到错误0001
    查看>>
    PHP引入了泛型和集合两大重要特性,大大改善 PHP 代码的可维护性和可读性
    查看>>
    PHP引擎php.ini参数优化
    查看>>
    PHP引用(&)使用详解
    查看>>
    php引用及垃圾回收
    查看>>
    php当前时间的集中写法
    查看>>
    php循环比较数组中的值,如何从PHP数组中计算值并在foreach循环中仅显示一次值?...
    查看>>