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

相关推荐
love is sour1 分钟前
深入浅出 jmap:Java 内存分析的“显微镜“
java·开发语言·测试工具·性能优化
想用offer打牌3 分钟前
虚拟内存与寻址方式解析(面试版)
java·后端·面试·系统架构
json{shen:"jing"}5 分钟前
2-C语言的运算符和表达式
c语言·开发语言
代码or搬砖6 分钟前
SQL核心语法总结:从基础操作到高级窗口函数
java·数据库·sql
AI视觉网奇11 分钟前
ue 虚幻引擎学习笔记
开发语言·虚幻引擎
月明长歌11 分钟前
【码道初阶】【Leetcode94&144&145】二叉树的前中后序遍历(非递归版):显式调用栈的优雅实现
java·数据结构·windows·算法·leetcode·二叉树
ghie909025 分钟前
使用MATLAB的k-Wave工具箱进行超声CT成像
开发语言·matlab
catchadmin25 分钟前
PHP 8.6 新增 clamp() 函数
开发语言·php
杰克尼32 分钟前
蓝桥云课-5. 花灯调整【算法赛】
java·开发语言·算法
.小墨迹32 分钟前
C++学习之std::move 的用法与优缺点分析
linux·开发语言·c++·学习·算法·ubuntu