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

相关推荐
sjh21002 小时前
STM32的计数模式和pwm模式
java·stm32·算法
nightunderblackcat2 小时前
新手向:Python实现数据可视化图表生成
开发语言·python·信息可视化
huluang3 小时前
PHP版本控制系统:高效文档管理
开发语言·php
草药味儿の岁月4 小时前
系统测试讲解 - Java使用selenium实现滑块验证的处理详解
java·python·selenium
火丁不是灯5 小时前
《 C Primer Plus》
c语言·开发语言
WSSWWWSSW8 小时前
Numpy科学计算与数据分析:Numpy文件操作入门之数组数据的读取和保存
开发语言·python·数据挖掘·数据分析·numpy
Lisonseekpan9 小时前
MVCC的底层实现原理是什么?
java·数据库·后端·mysql
芥子须弥Office9 小时前
从C++0基础到C++入门 (第二十五节:指针【所占内存空间】)
c语言·开发语言·c++·笔记
灰原喜欢柯南9 小时前
实战:MyBatis 中 db.properties 的正确配置与最佳实践
java·数据库·mybatis
中东大鹅9 小时前
SpringBoot实现文件上传
java·spring boot·后端