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

相关推荐
Circ.7 小时前
Python 调试 Litellm 本地大模型接口:模型列表与对话接口实操踩坑记录
开发语言·python
现任明教教主~9 小时前
Thinkphp站群蜘蛛池SaaS系统YanyvSEO含多用户/积分/六大引擎计费/易支付对接
java·开发语言·spring
Zhou1411369 小时前
SpringSecurity_02_授权与高级功能
开发语言·python
一条破秋裤10 小时前
Linux 线程创建:pthread_create 与基本回收
java·linux·运维
布吉岛的石头10 小时前
Java 程序员第 49 阶段5:BERT 预训练目标 MLM+NSP 的工程含义
java·人工智能·深度学习·bert·transformer
码匠许师傅10 小时前
【C++三方组件】cpp-httplib:一个头文件起 HTTP 服务
开发语言·c++·http
摇滚侠11 小时前
《On Java 中文版 基础卷》阅读笔记 对象无处不在 03
java·笔记·python
二十雨辰11 小时前
[学成在线]-01项目背景
java