我使用ByteBuddy实现包装器类,以为现有的域对象提供索引。
public interface Indexed {
Long getIndex();
}
这是我的领域课程。
public interface Alpha {
String getName();
Long getRating();
}
public static class AlphaImpl implements Alpha {
private final String name;
private final Long rating;
public AlphaImpl(String name, Long rating) {
this.name = name;
this.rating = rating;
}
@Override
public String getName() {
return name;
}
@Override
public Long getRating() {
return rating;
}
}
当我仅使用默认构造函数生成类并通过setter传递域对象和索引时,一切正常。
@Test
public void test1 () throws Exception {
Class<?> klass = new ByteBuddy()
.subclass(Alpha.class)
.implement(Indexed.class)
.defineProperty("origin", Alpha.class)
.method(ElementMatchers.isOverriddenFrom(Alpha.class))
.intercept(MethodCall.invokeSelf().onField("origin"))
.defineProperty("index", Long.class)
.make()
.load(AlphaImpl.class.getClassLoader())
.getLoaded();
Alpha origin = new AlphaImpl("Wrapped object", 10L);
Alpha indexed = (Alpha) klass.getConstructor().newInstance();
klass.getDeclaredMethod("setOrigin", Alpha.class).invoke(indexed, origin);
klass.getDeclaredMethod("setIndex", Long.class).invoke(indexed, 13L);
assertEquals("Wrapped object", indexed.getName());
assertEquals(10L, (long)indexed.getRating());
assertEquals(13L, (long)((Indexed)indexed).getIndex());
}
但是,当我将属性设置为只读并定义构造函数以对其进行设置时,我遇到了异常。
@Test
public void test2 () throws Exception {
Class<?> klass = new ByteBuddy()
.subclass(Alpha.class, ConstructorStrategy.Default.NO_CONSTRUCTORS
)
.implement(Indexed.class)
.defineConstructor(Visibility.PUBLIC)
.withParameters(Alpha.class, Long.class)
.intercept(
FieldAccessor.ofField("origin").setsArgumentAt(0)
.andThen(FieldAccessor.ofField("index").setsArgumentAt(1)))
.defineProperty("origin", Alpha.class, true)
.method(ElementMatchers.isOverriddenFrom(Alpha.class))
.intercept(MethodCall.invokeSelf().onField("origin"))
.defineProperty("index", Long.class, true)
.make()
.load(AlphaImpl.class.getClassLoader())
.getLoaded();
Alpha origin = new AlphaImpl("Wrapped object", 10L);
Alpha indexed = (Alpha) klass.getConstructor(Alpha.class, Long.class).newInstance(origin, 13L);
assertEquals("Wrapped object", indexed.getName());
assertEquals(10L, (long)indexed.getRating());
assertEquals(13L, (long)((Indexed)indexed).getIndex());
}
结果跟踪如下。
Constructor must call super() or this() before return
Exception Details:
Location:
IndexedWrapperTest$Alpha$ByteBuddy$V9ew7nId.<init>(LIndexedWrapperTest$Alpha;Ljava/lang/Long;)V @10: return
Reason:
Error exists in the bytecode
Bytecode:
0000000: 2a2b b500 102a 2cb5 001b b1
java.lang.VerifyError: Constructor must call super() or this() before return
Exception Details:
Location:
IndexedWrapperTest$Alpha$ByteBuddy$V9ew7nId.<init>(LIndexedWrapperTest$Alpha;Ljava/lang/Long;)V @10: return
Reason:
Error exists in the bytecode
Bytecode:
0000000: 2a2b b500 102a 2cb5 001b b1
at java.base/java.lang.Class.getDeclaredConstructors0(Native Method)
at java.base/java.lang.Class.privateGetDeclaredConstructors(Class.java:3138)
at java.base/java.lang.Class.getConstructor0(Class.java:3343)
at java.base/java.lang.Class.getConstructor(Class.java:2152)
at IndexedWrapperTest.test2(IndexedWrapperTest.java:95)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecutor.runTestClass(JUnitTestClassExecutor.java:106)
at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecutor.execute(JUnitTestClassExecutor.java:58)
at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecutor.execute(JUnitTestClassExecutor.java:38)
at org.gradle.api.internal.tasks.testing.junit.AbstractJUnitTestClassProcessor.processTestClass(AbstractJUnitTestClassProcessor.java:66)
at org.gradle.api.internal.tasks.testing.SuiteTestClassProcessor.processTestClass(SuiteTestClassProcessor.java:51)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:35)
at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
at org.gradle.internal.dispatch.ContextClassLoaderDispatch.dispatch(ContextClassLoaderDispatch.java:32)
at org.gradle.internal.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:93)
at com.sun.proxy.$Proxy2.processTestClass(Unknown Source)
at org.gradle.api.internal.tasks.testing.worker.TestWorker.processTestClass(TestWorker.java:117)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:35)
at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
at org.gradle.internal.remote.internal.hub.MessageHubBackedObjectConnection$DispatchWrapper.dispatch(MessageHubBackedObjectConnection.java:155)
at org.gradle.internal.remote.internal.hub.MessageHubBackedObjectConnection$DispatchWrapper.dispatch(MessageHubBackedObjectConnection.java:137)
at org.gradle.internal.remote.internal.hub.MessageHub$Handler.run(MessageHub.java:404)
at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:63)
at org.gradle.internal.concurrent.ManagedExecutorImpl$1.run(ManagedExecutorImpl.java:46)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
at org.gradle.internal.concurrent.ThreadFactoryImpl$ManagedThreadRunnable.run(ThreadFactoryImpl.java:55)
at java.base/java.lang.Thread.run(Thread.java:834)
如何解决该问题?
我如何检查结果类是否是具有最小开销的简单组合?
答案 0 :(得分:0)
我自己找到了解决方法。
我必须显式调用Objects默认构造函数,如下面的清单所示。引入 MethodCall.invoke(Object.class.getConstructor())行后,一切正常。
onclick