java 动态代理

有关Java的动态代理用法,写了一个demo,代码如下:

java 复制代码
package com.example.javalib;

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

public class MyClass {
    public static void main(String[] args) {
        new MyClass().testProxy();
    }

    interface IUserService {
        void addUser(String username);
        void deleteUser(int id);
        String getUser(int id);
    }

    private IUserService mUserService = new IUserService() {
            @Override
            public void addUser(String username) {
                System.out.println("addUser:" + username);
            }

            @Override
            public void deleteUser(int id) {
                System.out.println("删除用户ID:" + id);
            }

            @Override
            public String getUser(int id) {
                System.out.println("获取用户,ID:" + id);
                return "代号: " + id;
            }
        };

    private void testProxy() {
        System.out.println("原来调用流程:");
        mUserService.addUser("小龙女");
        mUserService.getUser(9527);

        System.out.println("------------------------");

        // 下面动态代理,原有功能不变,加点日志
        class LoggingHandler implements InvocationHandler {
            private IUserService target;
            public LoggingHandler(IUserService target) {
                this.target = target;
            }

            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                System.out.println("begin to invoke method: " + method.getName());
                long start = System.currentTimeMillis();

                // 为了原有功能保持不变,所以这里调用原始方法(是否调用原始方法根据业务需要, 甚至可以修改结果,也可以啥都不处理)
                Object result = method.invoke(target, args);

                long duration = System.currentTimeMillis() - start;
                System.out.println("finish invoke method " + method.getName() + ", cost time: " + duration + "ms");
                return result;
            }
        }


        IUserService proxy = (IUserService) Proxy.newProxyInstance(IUserService.class.getClassLoader()
        ,  new Class[]{IUserService.class}, new LoggingHandler(mUserService));

        // 模拟的一些实际业务场景,这里我通过反射把mUserService替换了。
        try {
            Field field = MyClass.class.getDeclaredField("mUserService");
            field.setAccessible(true);
            field.set(MyClass.this, proxy);
        } catch (Exception e) {
            e.printStackTrace();
        }

        System.out.println("使用动态代理后调用流程:");
        mUserService.addUser("小龙女");
        mUserService.getUser(9527);
    }   
}

打印:

ok. 动态代理可以用于拦截接口调用,修改其实现,或者可以加日志、监控性能、敏感接口权限校验等等。这有利用业务解耦。某些框架也使用到动态代理。缺点就是使用反射对性能有损耗。

相关推荐
斯维赤6 分钟前
限流、熔断、降级,你真的分得清吗?
java·后端·架构
Evand J1 小时前
【MATLAB例程介绍】(17)永磁同步电机(PMSM)基于自适应无迹卡尔曼滤波(AUKF)的电流噪声在线估计。测量噪声协方差自适应与转速估计对比仿真
开发语言·matlab·卡尔曼滤波·无迹卡尔曼滤波·pmsm·电机滤波
BaiPeter2 小时前
ZPL文件预览
开发语言·c++
aiks_yuan3 小时前
Java CPU 100% 怎么排查:JDK 11 起 jstack 自带线程 CPU 时间,不用再 top -H 换算十六进制(JDK 8、11、17 实测)
java
Flynn Liang4 小时前
AiServices 源码级拆解:一个接口如何变成 RAG Agent
java·langchain·源码分析·rag·langchain4j·aiservices
Flynn Liang4 小时前
LangChain4j 1.23 架构全景:Java 大模型应用的 6 层抽象
java·langchain·大模型·rag·ai agent·langchain4j
聪明的笨猪猪5 小时前
实际工程问题:AI生成Redis分布式锁的原子性缺陷导致库存超卖
java·经验分享·面试·ai编程
软件技术NINI6 小时前
基于SpringBoot和Vue的新能源汽车销售推荐系统
java·vue.js·spring boot·后端·汽车·毕业设计·毕设
Flynn Liang6 小时前
LangChain4j 生产级工程骨架:12 个模块 + Docker 一键启动
java·spring boot·langchain·rag·langchain4j
噢,我明白了7 小时前
JAVA中的一些基础应用知识点
java·开发语言