• Java高级-动态代理


    动态代理

    1.介绍

    在这里插入图片描述

    public interface Star {
        String sing(String name);
        void dance();
    }
    
    public class BigStar implements Star{
        private String name;
    
        public BigStar(String name) {
            this.name = name;
        }
    
        public String sing(String name) {
            System.out.println(this.name + "正在唱:" + name);
            return "谢谢!谢谢!";
        }
    
        public void dance() {
            System.out.println(this.name + "正在跳舞");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    // 类似于中介公司
    public class ProxyUtil {
        public static Star createProxy(BigStar bigStar) {
            //参数1:CLassLoader 用于指定一个类加载器
            //参数2:interfaces 指定生成的代理长什么样,也就是有什么方法
            //参数3:InvocationHandler 指定生成的代理对象要干什么事情
            Star starProxy = (Star) Proxy.newProxyInstance(ProxyUtil.class.getClassLoader(), new Class[]{Star.class}, new InvocationHandler() {
                @Override
                public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                    // 代理对象要做的事情,会在这里写代码
                    if (method.getName().equals("sing")) {
                        System.out.println("代理准备话筒,收钱20万");
                    } else if (method.getName().equals("dance")) {
                        System.out.println("代理准备场地,收钱20万");
                    }
                    return method.invoke(bigStar, args);
                }
            });
            return starProxy;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    // 测试类
    public class Test {
        public static void main(String[] args) {
            BigStar s = new BigStar("杨超越");
            Star starProxy = ProxyUtil.createProxy(s);
            
            String rs = starProxy.sing("好日子");
            System.out.println("rs = " + rs);
            
            starProxy.dance();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    2.案例

    案例:使用代理优化用户管理类
    场景:某系统有一个用户管理类,包含登录,删除用户,查询用户等功能,系统要求统计每个功能的执行耗时情况,以便后期观察程序性能
    需求:现在已经开发好了该模块,找出目前存在的问题,并对其进行改造

    /**
     * 用户业务接口
     */
    public interface UserService {
        // 登录功能
        void login(String loginName,String passWord) throws Exception;
        // 删除用户
        void deleteUser() throws Exception;
        // 查询用户,返回数组的形式
        String[] selectUsers() throws Exception;
    }
    
    public class UserServiceImpl implements UserService{
        @Override
        public void login(String loginName, String passWord) throws Exception {
            long startTime = System.currentTimeMillis();
    
            if ("admin".equals(loginName) && "123456".equals(passWord)) {
                System.out.println("登录成功");
            } else {
                System.out.println("登录失败");
            }
            Thread.sleep(1000);
    
            long endTime = System.currentTimeMillis();
            System.out.println("login方法执行耗时:" + (endTime - startTime)/1000.0 + "s");
        }
    
        @Override
        public void deleteUser() throws Exception{
            long startTime = System.currentTimeMillis();
    
            System.out.println("成功删除1万个用户");
            Thread.sleep(1500);
    
            long endTime = System.currentTimeMillis();
            System.out.println("deleteUser方法执行耗时:" + (endTime - startTime)/1000.0 + "s");
        }
    
        @Override
        public String[] selectUsers() throws Exception{
            long startTime = System.currentTimeMillis();
    
            System.out.println("查询出3个用户");
            String[] names = {"张三", "李四", "王五"};
    
            long endTime = System.currentTimeMillis();
            System.out.println("deleteUser方法执行耗时:" + (endTime - startTime)/1000.0 + "s");
            return names;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51

    存在的问题:主要业务逻辑不应该包含时间相关的代码
    解决办法:将时间相关的代码通过代理模式实现,把业务类的相关代码删除

    public class UserServiceProxy {
        public static UserService createProxy(UserService userService) {
            UserService userServiceProxy = (UserService) Proxy.newProxyInstance(UserServiceProxy.class.getClassLoader(),
                    new Class[]{UserService.class}, new InvocationHandler() {
                @Override
                public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                    if (method.getName().equals("login") || method.getName().equals("deleteUser") ||
                        method.getName().equals("selectUsers")) {
                        long startTime = System.currentTimeMillis();
    
                        Object rs = method.invoke(userService, args);
    
                        long endTime = System.currentTimeMillis();
                        System.out.println(method.getName() + "方法执行耗时:" + (endTime - startTime)/1000.0 + "s");
                        return rs;
                    } else {
                        Object rs = method.invoke(userService, args);
                        return rs;
                    }
                }
            });
    
            return userServiceProxy;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
  • 相关阅读:
    找实习之从0开始的后端学习日记【9.19】
    软件工程——设计模式之创建型模式(单例模式、抽象工厂模式、建造者模式、工厂模式、原型模式。)
    公益理发暖人心,爱心助老绿萝先行
    如何在TIA博途中在线更新PLC的CPU固件版本?
    Java真过饱和了吗?现在学Java迟了?
    技巧分享:图片怎么去水印?
    Kelper.js 笔记 python交互
    C++的map用法
    rsync远程同步
    【Matplotlib绘制图像大全】(十八):Matplotlib绘制条形码
  • 原文地址:https://blog.csdn.net/weixin_46926189/article/details/133146477