我正在尝试使用OGM将对象转换为OrientDB的Vertex。目前我正在使用GCLib,但我读到ByteBuddy可以实现两个关键的事情,如果工作,它将提高OGM速度。
ByteBuddy可以实现字段访问控制吗?我阅读了文档,但不清楚,或者我不理解。
Dinamically添加默认的空构造函数。
目前的问题是:我们不知道将作为参数传递的类定义。我们的想法是重新定义类并实现空构造函数(如果没有),如果检测到assign操作,则添加一个名为__BB__Dirty的字段将对象设置为脏,并强制实现接口与对象进行通信。
实施例: 通用类:
public class Example {
int i = 0;
String stringField;
public Example(Strinf s) {
stringField = s;
}
public void addToI(){
i++;
}
}
现在我们有了这样的界面:
public interface DirtyCheck {
public boolean isDirty();
}
所以,我想强制Example类实现接口,方法isDirty(),要处理的字段和默认的构造函数,以便将类转换为:
public class Example implements DirtyCheck {
int i = 0;
String stringField;
boolean __BB__dirty = false;
public Example() {
}
public Example(Strinf s) {
stringField = s;
}
public void addToI(){
i++;
}
public boolean isDirty() {
return this.__BB__dirty;
}
}
和一些神奇的分配器因此如果修改了任何字段(__BB__dirty除外),__BB__dirty字段将设置为True;
我已经尝试了第一部分,但我失败了:(
...
ByteBuddyAgent.install();
Example ex = new ByteBuddy()
.redefine(Example.class)
.defineField("__BB__Dirty", boolean.class, Visibility.PUBLIC)
.make()
.load(Example.class.getClassLoader(), ClassReloadingStrategy.fromInstalledAgent())
.getLoaded().newInstance();
....
ex.addToI(); // <--- this should set __BB__dirty to true since it
// assign a value to i.
但是我收到了这个错误:
Exception in thread "main" java.lang.UnsupportedOperationException: class redefinition failed: attempted to change the schema (add/remove fields)
at sun.instrument.InstrumentationImpl.redefineClasses0(Native Method)
at sun.instrument.InstrumentationImpl.redefineClasses(InstrumentationImpl.java:170)
at net.bytebuddy.dynamic.loading.ClassReloadingStrategy$Strategy$1.apply(ClassReloadingStrategy.java:297)
at net.bytebuddy.dynamic.loading.ClassReloadingStrategy.load(ClassReloadingStrategy.java:173)
at net.bytebuddy.dynamic.DynamicType$Default$Unloaded.load(DynamicType.java:4350)
at Test.TestBB.<init>(TestBB.java:33)
at Test.TestBB.main(TestBB.java:23)
我陷入了解决BB问题的第一阶段。 感谢
答案 0 :(得分:0)
Java虚拟机不支持在重新定义类时更改已加载的类的布局。这不是Byte Buddy的限制,而是VM的实现。
为了做你想做的事,你应该看一下AgentBuilder
API,它允许你在加载之前修改类。但是,创建代理需要在启动时将其显式添加为代理(而不是将库添加到类路径中。
您可以通过调用:
来实现该接口.implement(DirtyCheck.class).intercept(FieldAccessor.of("__dirty__");
您还可以通过简单地定义一个默认构造函数来添加:
.defineConstructor(Visibility.PUBLIC).intercept(SuperMethodCall.INSTANCE)
后一个定义要求超类定义默认构造函数。