栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

JDK 动态代理

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

JDK 动态代理

一、静态代理-代理设计模式

        1.创建方法接口,目标类和代理类实现这个接口

        2. 代理类中包含目标类的成员变量,通过构造函数进行传参

// 传统静态代理
public class UserProxy implements UserService {

    private UserService userService;

    public UserProxy(UserService userService) {
        this.userService = userService;
    }

    @Override
    public User getUserByName(String username, Integer age) {
        getCurDate();
        User user = userService.getUserByName(username, age);
        Commit();
        return user;
    }

    @Override
    public int getUserCounts() {
        getCurDate();
        int count = userService.getUserCounts();
        Commit();
        return count;
    }

    // 代理类增强方法
    public void getCurDate() {
        Date date = new Date();
        SimpleDateFormat dft = new SimpleDateFormat("yyyy-MM-dd");
        String curDate = dft.format(date);
        System.out.println(curDate);
    }

    public void Commit() {
        System.out.println("事务提交");
    }

}

        问题:代码冗余,增强的功能需要添加在所有需要的方法中,当目标类增多的时候,需要为每个目标类都要创建代理类;否则,使用成员变量的方式也会造成一个类中方法量过多,不易管理

二、JDK动态代理

        使用java虚拟机的类加载机制:

  1. 通过一个类的全限定名来获取定义此类的二进制字节流
  2. 将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构
  3. 在内存中生成一个代表这个类的 java.lang.Class 对象,作为方法区这个类的各种数据访问入口

动态代理分为:JDK动态代理和cglib动态代理,两者分别基于接口实现和类继承实现

jdb动态代理:

        1.创建Proxy对象,通过newInstance方法获取代理对象实例;

        2.newInstance中的三个参数:目标类的类加载器,接口全限定类,InvocationHandler对象

public class UserDynamicProxy {

    private UserService userService;

    public UserDynamicProxy(UserService userService) {
        this.userService = userService;
    }

    // 通过动态代理获取代理对象
    public Object getObject() {

        // jdk动态代理固定参数:目标类加载器,目标接口,InvocationHandler对象
        Object proxy = Proxy.newProxyInstance(userService.getClass().getClassLoader(),
                new Class[]{UserService.class},
                (object, method, args) -> {
                 // 增强方法
                    Object res = method.invoke(userService, args);
                    System.out.println("提交事务");
                    return res; // 这是个代理对象
                }
                );
       
        return proxy;
    }

}

测试方法:

    @Test
    public void testDynamicProxy() {
        UserService userService = new UserServiceImpl();
        UserDynamicProxy userDynamicProxy = new UserDynamicProxy(userService);
        UserService proxy = (UserService) userDynamicProxy.getObject();
        User user = proxy.getUserByName("娜美", 18);
        System.out.println("dynamic user:" + user);
        System.out.println("-----------华丽分割线-------------");
        int count = proxy.getUserCounts();
        System.out.println("数量:" + count);

    }

测试发现,在newInstance中设置一次增强方法,UserService的所有方法都会被添加

jdk动态代理和cglib区别

JDK动态代理:基于Java反射机制实现,必须要实现了接口的业务类才能用这种办法生成代理对象。

cglib动态代理:基于ASM机制实现,通过生成业务类的子类作为代理类。

JDK Proxy 的优势:

  • 最小化依赖关系,减少依赖意味着简化开发和维护,JDK 本身的支持,可能比 cglib 更加可靠。
  • 平滑进行 JDK 版本升级,而字节码类库通常需要进行更新以保证在新版 Java 上能够使用。
  • 代码实现简单。

    基于类似 cglib 框架的优势:

  • 无需实现接口,达到代理类无侵入
  • 只操作我们关心的类,而不必为其他相关类增加工作量。
  • 高性能

    cglib感觉看不下去,之后来补上吧。。。。

    spring中的aop机制就是依靠动态代理进行实现的,统一了cglib和jdk动态代理实现上的差异,给出了统一的规范,简化了学习的困难。

    spring:   spring复习_右眸Remnant的博客-CSDN博客

  • 转载请注明:文章转载自 www.mshxw.com
    本文地址:https://www.mshxw.com/it/709002.html
    我们一直用心在做
    关于我们 文章归档 网站地图 联系我们

    版权所有 (c)2021-2022 MSHXW.COM

    ICP备案号:晋ICP备2021003244-6号