Java 用来代替反射的工具 reflect-linker

499 阅读1分钟

1. 应用场景

当你有一个只能用Object来表示的对象

// in User.java
class User {  
    String name = " user'name ";  
    String getName() {  
        return name;  
    }  
}
// in Main.java
Object user = Class.forName("io.github.hhy.test.User").newInstance();

你需要访问user这个对象的字段或者方法时, 大多人都会使用反射去操作, 这个时候你可以考虑使用 reflect-linker

引入依赖

<dependency>  
    <groupId>io.github.hhy50</groupId>  
    <artifactId>reflect-linker</artifactId>  
    <version>1.0.6</version>  
</dependency>
// in UserVisitor.java
// 需要提前定义访问规则
@Target.Bind("io.github.hhy.test.User")  
public interface UserVisitor {  
    // 指定字段 getter  
    @Field.Getter("name")  
    String getName();  

    // 指定字段 setter  
    @Field.Setter("name")  
    void setName(String name);  

    // 指定方法  
    @Method.Name("getName")  
    String getNameMethod();  
}

// in Main.java
Object user = Class.forName("io.github.hhy.test.User").newInstance();  
UserVisitor linker = LinkerFactory.createLinker(UserVisitor.class, user);  
System.out.println(linker.getName());

2. 优势

强大的链式访问能力

@Target.Bind("io.github.hhy.test.User")  
public interface UserVisitor {  
    // 链式访问String的value字段
    @Field.Getter("name.value")  
    char[] getNameCharArray();
    
    // 调用String的父类方法。也就是Object里面的toString()  
    @Method.InvokeSuper  
    @Method.Name("name.toString")  
    String nameSuperToString();
  
    // 链式调用String.length()方法
    @Method.Name("name.length")  
    int nameLen();
}

可以支持多级的链式访问/调用

优雅的类型转换

reflect-linker支持方法返回一个链接器, 也支持在参数里面使用链接器

@Target.Bind("io.github.hhy.test.User")  
public interface UserVisitor {  
    @Field.Getter("name")  
    MyString getName();
    
    @Field.Setter("name")  
    void setName(MyString name);  
}

// 链接到 String  
@Target.Bind("java.lang.String")  
interface MyString {  
  
}

运行时类型

运行时类型是指 @Target.Bind指定的类为实际类的父类

手动将User类的字段和方法移动到他的子类中, 上面的链接器依然有效

class User {}
class UserVo extends User {
    String name = " user'name ";  
    String getName() {  
        return name;  
    }
}
// UserVisitor
@Target.Bind("io.github.hhy.test.User")  
public interface UserVisitor {
    //....
}

// Main.java
// 这里也需要改成
Object user = Class.forName("io.github.hhy.test.UserVo").newInstance();

3. 总结

reflect-linker很轻量化, 仅依赖了asm来动态生成接口类的实现类

项目地址:github.com/hhy50/refle…