reflect-linker 是一个用于链接反射对象的库,它可以帮助你在运行时代替反射去使用对象中字段和方法。
简单尝试:
- 引入依赖
<dependency>
<groupId>io.github.hhy</groupId>
<artifactId>reflect-linker</artifactId>
<version>1.0.0</version>
</dependency>
- 定义访问规则 以ArrayList举例
@Target.Bind("java.util.ArrayList")
public interface MyArrayList {
void add(Object o);
@Field.Getter("elementData")
Object[] getElementData();
@Field.Setter("elementData")
void setElementData(Object[] elementData);
}
- 创建连接器
class Example {
public static void main(String[] args) throws LinkerException {
MyArrayList list = LinkerFactory.createLinker(MyArrayList.class, new ArrayList<>());
// do thing
}
}
- 链式表达式访问
class User {
private String name;
private int age;
}
class UserWrap {
private User user;
}
@Target.Bind("io.github.hhy50.linker.example.nest.UserWrap")
interface UserVisitor {
@Field.Getter("user")
User getUser();
@Field.Setter("user")
void setUser(User user);
@Field.Setter("user.name")
void setName(String val);
@Field.Getter("user.name")
String getName();
@Field.Setter("user.age")
void setAge(int val);
@Field.Getter("user.age")
int getAge();
}
class Example {
public static void main(String[] args) throws LinkerException {
UserWrap userWrap = new UserWrap();
UserVisitor userVisitor = LinkerFactory.createLinker(UserVisitor.class, userWrap);
userVisitor.setUser(new User());
userVisitor.setAge(20);
userVisitor.setName("example");
// do something
}
}
- 动态类型
class A { }
class B {
String val = "this is b'val";
}
class A2 extends A {
private B b;
public A2(B b) {
this.b = b;
}
}
class MyObject {
private A a;
}
@Target.Bind("io.github.hhy50.linker.example.dynamic.MyObject")
interface MyObjectVisitor {
@Field.Setter("a")
void setA(A val);
@Field.Getter("a.b")
B getB();
}
class Example {
public static void main(String[] args) throws LinkerException {
MyObject myObj = new MyObject();
MyObjectVisitor myObjVisitor = LinkerFactory.createLinker(MyObjectVisitor.class, myObj);
myObjVisitor.setA(new A2(new B()));
System.out.println(myObjVisitor.getB().val);
// do something
}
}
上面表达式@Field.Getter("a.b")
中, A class
是没有B field
的, B field
存在于A
的子类中, 这样的字段视为运行时字段, 这样会在调用对应方法时动态获取A
的类型
如果您非常在意执行性能, 可以使用@Typed
指定A class
的类型, 将B field
变为已知的字段
//@Typed(name = "a", type = "io.github.hhy50.linker.example.dynamic.A2") // 也可以声明在这里
@Target.Bind("io.github.hhy50.linker.example.dynamic.MyObject")
interface MyObjectVisitor {
@Field.Setter("a")
void setA(A val);
@Typed(name = "a", type = "io.github.hhy50.linker.example.dynamic.A2")
@Field.Getter("a.b")
B getB();
}
然后重新run