ReflectASM高性能反射Java库

1. 简介

  在日常开发中,经常需要使用反射操作类中的属性或方法。ReflectASM是一个非常小的 Java 库,它提供高性能反射能力。
  Github地址:https://github.com/EsotericSoftware/reflectasm

2. 官方性能报告



3. 用法

ReflectASM仅可访问public属性和方法。

  • pom引入依赖
<dependency>
    <groupId>com.esotericsoftware</groupId>
    <artifactId>reflectasm</artifactId>
    <version>{latest.version}</version>
</dependency>
  • 使用 ReflectASM 的构造函数反射:
ConstructorAccess<User> constructorAccess = ConstructorAccess.get(User.class);
User user = constructorAccess.newInstance();
  • 使用 ReflectASM 的属性反射:
User user = new User();
FieldAccess fieldAccess = FieldAccess.get(User.class);
fieldAccess.set(user, "username", "张三");
String name = (String) fieldAccess.get(user, "username");
  • 使用 ReflectASM 的方法反射:
User user = new User();
MethodAccess methodAccess = MethodAccess.get(User.class);
methodAccess.invoke(user, "setUserame", "张三");
String username = (String) methodAccess.invoke(user, "getUsername");
  • 使用 ReflectASM 的属性索引反射(推荐):
User user = new User();
FieldAccess fieldAccess = FieldAccess.get(User.class);
int index = fieldAccess.getIndex("username");
fieldAccess.set(user, index, "张三");
String username = (String) fieldAccess.get(user, index);
  • 使用 ReflectASM 的方法索引反射(推荐):
User user = new User();
MethodAccess methodAccess = MethodAccess.get(User.class);
int setIndex = methodAccess.getIndex("setUserame");
int getIndex = methodAccess.getIndex("getUsername");
methodAccess.invoke(user, setIndex, "张三"
String username = (String) methodAccess.invoke(user, getIndex);

4. 单元测试

import com.esotericsoftware.reflectasm.ConstructorAccess;
import com.esotericsoftware.reflectasm.FieldAccess;
import com.esotericsoftware.reflectasm.MethodAccess;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;
import org.springframework.util.StopWatch;

import java.lang.reflect.Method;

/**
 * 高性能反射Java库 单元测试
 *
 * @author CL
 */
@Slf4j
public class ReflectAsmTest {

    /**
     * 测试方案:循环 n 次,通过set方法设置值,然后通过get方法获取值<br/>
     */
    @Test
    public void test() throws Exception {
//        final String FIELD_NAME = "username";
        final String SET_METHOD_NAME = "setUsername";
        final String GET_METHOD_NAME = "getUsername";
        // 次数
        int n = 1_0000;

        StopWatch stopWatch = new StopWatch();

        stopWatch.start("Java反射");

        Class<User> clazz = User.class;
//        Field field = clazz.getDeclaredField(FIELD_NAME);
//        field.setAccessible(true);
        Method setMethod = clazz.getDeclaredMethod(SET_METHOD_NAME, String.class);
        Method getmethod = clazz.getDeclaredMethod(GET_METHOD_NAME);

        for (int i = 1; i <= n; i++) {
            User user = clazz.newInstance();

            setMethod.invoke(user, "方法" + i);

            Object invoke = getmethod.invoke(user);
//            log.debug("get值:{}", invoke);
        }

        stopWatch.stop();

        stopWatch.start("ReflectAsm反射");

        ConstructorAccess<User> constructorAccess = ConstructorAccess.get(User.class);
        FieldAccess fieldAccess = FieldAccess.get(User.class);
        MethodAccess methodAccess = MethodAccess.get(User.class);

        for (int i = 1; i <= n; i++) {
            User user = constructorAccess.newInstance();

            methodAccess.invoke(user, SET_METHOD_NAME, "方法" + i);

            Object invoke = methodAccess.invoke(user, GET_METHOD_NAME);
//            log.debug("get值:{}", invoke);
        }

        stopWatch.stop();

        stopWatch.start("ReflectAsm反射(优化)");

        int setIndex = methodAccess.getIndex(SET_METHOD_NAME);
        int getIndex = methodAccess.getIndex(GET_METHOD_NAME);
        for (int i = 1; i <= n; i++) {
            User user = constructorAccess.newInstance();

            methodAccess.invoke(user, setIndex, "方法" + i);

            Object invoke = methodAccess.invoke(user, getIndex);
//            log.debug("get值:{}", invoke);
        }

        stopWatch.stop();

        for (StopWatch.TaskInfo taskInfo : stopWatch.getTaskInfo()) {
            log.info("{} 耗时:{} ms", taskInfo.getTaskName(), taskInfo.getTimeMillis());
        }
    }
    
}

class User {

    private String username;

    public User() {
    }

    public User(String username) {
        this.username = username;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

}

  100次循环单元测试结果:

23:54:37.630 [main] INFO com.c3stones.reflectasm.ReflectAsmTest - Java反射 耗时:3 ms
23:54:37.635 [main] INFO com.c3stones.reflectasm.ReflectAsmTest - ReflectAsm反射 耗时:21 ms
23:54:37.635 [main] INFO com.c3stones.reflectasm.ReflectAsmTest - ReflectAsm反射(优化) 耗时:0 ms

  1000次循环单元测试结果:

23:55:07.161 [main] INFO com.c3stones.reflectasm.ReflectAsmTest - Java反射 耗时:7 ms
23:55:07.168 [main] INFO com.c3stones.reflectasm.ReflectAsmTest - ReflectAsm反射 耗时:35 ms
23:55:07.168 [main] INFO com.c3stones.reflectasm.ReflectAsmTest - ReflectAsm反射(优化) 耗时:1 ms

  10000次循环单元测试结果:

23:55:27.604 [main] INFO com.c3stones.reflectasm.ReflectAsmTest - Java反射 耗时:44 ms
23:55:27.611 [main] INFO com.c3stones.reflectasm.ReflectAsmTest - ReflectAsm反射 耗时:49 ms
23:55:27.611 [main] INFO com.c3stones.reflectasm.ReflectAsmTest - ReflectAsm反射(优化) 耗时:7 ms
posted @ 2023-04-07 22:03  C3Stones  阅读(865)  评论(0编辑  收藏  举报