当前位置: 首页 > article >正文

Java动态代理--思想

动态代理

案例引入

  • 需求

    模拟某企业用户管理业务,需包含用户登录,用户删除,用户查询功能,并要统计每个功能的耗时。

  • 分析

    定义一个UserService表示用户业务接口,规定必须完成用户登录,用户删除,用户查询功能。

    定义一个实现类UserServiceImpl实现UserService,并完成相关功能,且统计每个功能的耗时。

    定义测试类,创建实现类对象,调用方法。

示例代码

/*
    模拟用户业务功能
 */
public interface UserService {
    String login(String username,String password);
    void findUser();
    boolean removeUser();
}

public class UserServiceImpl implements UserService{
    @Override
    public String login(String username, String password) {
        long startTime = System.currentTimeMillis();
        try{
            Thread.sleep(1000);
            if ("admin".equals(username) && "123".equals(password)) {
                return "success";
            }
            return "用户名或密码有误";
        }catch (Exception e){
            e.printStackTrace();
            return "error";
        }finally {
            long endTime = System.currentTimeMillis();
            System.out.println("login 花费了:"+(endTime-startTime)/1000+"s");
        }
    }

    @Override
    public void findUser() {
        long startTime = System.currentTimeMillis();
        System.out.println("找到300个用户信息");
        try{
            Thread.sleep(2000);
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            long endTime = System.currentTimeMillis();
            System.out.println("findUser 花费了:"+(endTime-startTime)/1000+"s");
        }
    }

    @Override
    public boolean removeUser() {
        long startTime = System.currentTimeMillis();
        System.out.println("删除 300个用户信息");
        try{
            Thread.sleep(500);
            return true;
        }catch (Exception e){
            e.printStackTrace();
            return false;
        }finally {
            long endTime = System.currentTimeMillis();
            System.out.println("removeUser 花费了:"+(endTime-startTime)/1000+"s");
        }
    }
}

public class Test {
    public static void main(String[] args) {
        UserService userService = new UserServiceImpl();
        System.out.println(userService.login("admin","123"));
        System.out.println(userService.removeUser());
        userService.findUser();
    }
}

案例存在问题

  • 每个方法都要进行性能统计
  • 大量重复的代码

解决案例问题–动态代理

什么是动态代理

​ 代理就是被代理者没有能力或者不愿意去完成某件事情,需要找个人代替自己去完成这件事,动态代理就是用来对业务功能(方法)进行代理的

动态代理关键步骤

  1. 必须有接口,实现类要实现接口(代理通常是基于接口实现的)。
  2. 创建一个实现类的对象,该对象为业务对象,紧接着为业务对象做一个代理对象。

在这里插入图片描述

示例代码

/*
    模拟用户业务功能
 */
public interface UserService {
    String login(String username,String password);
    void findUser();
    boolean removeUser();
}
public class UserServiceImpl implements UserService{
    @Override
    public String login(String username, String password) {
        try{
            Thread.sleep(1000);
            if ("admin".equals(username) && "123".equals(password)) {
                return "success";
            }
            return "用户名或密码有误";
        }catch (Exception e){
            e.printStackTrace();
            return "error";
        }
    }

    @Override
    public void findUser() {
        System.out.println("找到300个用户信息");
        try{
            Thread.sleep(2000);
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    @Override
    public boolean removeUser() {
        System.out.println("删除 300个用户信息");
        try{
            Thread.sleep(500);
            return true;
        }catch (Exception e){
            e.printStackTrace();
            return false;
        }
    }
}


PRoxyUtil 动态代理工具类

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/*
    public static Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h)
    参数:
        参数一:类加载器,负责加载代理类到内存中使用
        参数二:获取被代理的对象实现的全部接口,代理腰围全部接口的 全部方法进行代理
        参数三:代理的核心处理逻辑
 */
public class ProxyUtil {
    /*
        生成业务对象的代理对象
        @param userService
        @return
     */
    public static UserService getProxy(UserServiceImpl userService) {
        // 返回了一个代理对象
        return (UserService) Proxy.newProxyInstance(userService.getClass().getClassLoader(), userService.getClass().getInterfaces()
                , new InvocationHandler() {
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        // 参数一: 代理对象本身
                        // 参数二: 正在被代理的方法
                        // 参数三: 被代理方法应传入的参数
                        long startTime = System.currentTimeMillis();
                        // 马上触发方法的真正执行(触发真正的业务功能)
                        Object res = method.invoke(userService, args);
                        long endTime = System.currentTimeMillis();
                        System.out.println("removeUser 花费了:"+(endTime-startTime)/1000+"s");
                        // 把业务动能方法执行的结构返回给调用者
                        return res;
                    }
                });
    }
}

Test 测试类

public class Test {
    public static void main(String[] args) {
        // 1.把业务对象直接做成一个代理对象返回,代理对象的类型也是 UserService
//        UserService userService = new UserServiceImpl();
        UserService userService = ProxyUtil.getProxy(new UserServiceImpl());
        System.out.println(userService.login("admin","123"));
        System.out.println(userService.removeUser());
        userService.findUser();
    }
}

动态代理的优点

  • 非常的灵活,支持任意接口类型的实现类对象做代理,也可以直接为接本身做代理。
  • 可以为被代理对象的所有方法做代理。
  • 可以在不改变方法源码的情况下,实现对方法功能的增强。
  • 不仅简化了编程工作、提高了软件系统的可扩展性,同时也提高了开发效率。

任意接口的实现类做做代理代码示例

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/*
    public static Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h)
    参数:
        参数一:类加载器,负责加载代理类到内存中使用
        参数二:获取被代理的对象实现的全部接口,代理腰围全部接口的 全部方法进行代理
        参数三:代理的核心处理逻辑
 */
public class ProxyUtil {
    /*
        生成业务对象的代理对象
        @param userService
        @return
     */
    public static <T> T getProxy(T obj) {
        // 返回了一个代理对象
        return (T) Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces()
                , new InvocationHandler() {
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        // 参数一: 代理对象本身
                        // 参数二: 正在被代理的方法
                        // 参数三: 被代理方法应传入的参数
                        long startTime = System.currentTimeMillis();
                        // 马上触发方法的真正执行(触发真正的业务功能)
                        Object res = method.invoke(obj, args);
                        long endTime = System.currentTimeMillis();
                        System.out.println("removeUser 花费了:"+(endTime-startTime)/1000+"s");
                        // 把业务动能方法执行的结构返回给调用者
                        return res;
                    }
                });
    }
}

= System.currentTimeMillis();
System.out.println(“removeUser 花费了:”+(endTime-startTime)/1000+“s”);
// 把业务动能方法执行的结构返回给调用者
return res;
}
});
}
}



http://www.kler.cn/a/7816.html

相关文章:

  • 视频编码基础入门
  • STM32芯片EXIT外部中断的配置与原理
  • 数据库范式、MySQL 架构、算法与树的深入解析
  • IOT物联网低代码可视化大屏解决方案汇总
  • C# WPF FontDialog字体对话框,ColorDialog颜色对话框 引用
  • UAC2.0 speaker——同时支持 16bit,24bit 和 32bit
  • 网络安全从业人员应该如何提升自身的web渗透能力?
  • java面试八股文_虚拟机篇(jvm)
  • ThinkPHP路由不转换的原因及解决方法
  • 2023年PMP考生|考前必练全真模拟题分享,附答案解析
  • 从零开始实现一个C++高性能服务器框架----Hook模块
  • 8. 字符串转换整数 (atoi)
  • 求给定集合中好数对的个数
  • AST解混淆
  • mysql双游标嵌套循环
  • 开源Icon大合集
  • .net特性(个人笔记)
  • WRF-cmaq模式
  • Qt——实现一个简单的获取文件信息的dialog
  • 蓝易云:Linux系统命令-ls命令详细介绍.系列【9】
  • Java练习题
  • 华为OD机试-投篮大赛-2022Q4 A卷-Py/Java/JS
  • Windows编程基础
  • 基于SpringBoot+Vue家乡特色推荐系统
  • 获得lazada商品详情 API
  • 4.5-4.6学习总结