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

相关推荐
XIAEE11 分钟前
一个即时通讯项目是怎么长出来的:(Spring Boot 3 + Vue 3 微前端 + 悟空 IM + LiveKit)
java·spring
n876518 分钟前
Playwright Java WEB UI 自动化实现框架与逻辑
java·前端·ui
Java_AI工程师18 分钟前
Spring4 / SpringBoot1.x 老项目想接入 AI?不用升级框架!3 套无痛落地方案
java·人工智能·spring boot
BBmmo18 分钟前
Java Stream 的 filter 为什么看起来没运行?
java
VimorphTech23 分钟前
Java 文件缓存实战:如何避免读到未下载完成的视频?
java·spring boot
爱喝热水的呀哈喽33 分钟前
HEJIAN RESEARCH
开发语言·matlab
白露与泡影40 分钟前
后端 Java 面试核心八股汇总|高频面试题 + 解析,覆盖基础到进阶
java·开发语言·面试
xifangge20251 小时前
基于 JavaScript 实现 CNC 数控切削参数与螺纹公差纯前端核算引擎
开发语言·前端·javascript
“AI国潮设计-小江”1 小时前
【AIGC实战】Python+SDXL批量生成「潮汕英歌舞冰淇淋蛋糕&红桃粿咖啡」IP,固定角色形象批量出甜品商业效果图
开发语言·人工智能·python·prompt·aigc
SL_staff1 小时前
JVS-APS 实践:用双向反馈闭环打破制造计划孤岛
java·spring cloud·全栈