我正在尝试创建一种自定义注释处理机制(检索注释值并将其传递到字段的构造函数中),例如
@Find(by = CSS, locator = "[data-qa=username]")
private Input username;
在JDK 8中,不同的反射操作非常适合我。但是,由于以下异常(请注意,在后台使用了jOOR模块),所以我无法再访问注解的方法(在Java 11中)。 ,但是如果我使用纯Java反射,也会发生相同的问题):
java.lang.IllegalAccessException: class org.joor.Reflect (in module org.jooq.joor) cannot access class com.sun.proxy.jdk.proxy2.$Proxy9 (in module jdk.proxy2) because module jdk.proxy2 does not export com.sun.proxy.jdk.proxy2 to module org.jooq.joor
org.joor.ReflectException: java.lang.IllegalAccessException: class org.joor.Reflect (in module org.jooq.joor) cannot access class com.sun.proxy.jdk.proxy2.$Proxy9 (in module jdk.proxy2) because module jdk.proxy2 does not export com.sun.proxy.jdk.proxy2 to module org.jooq.joor
at org.jooq.joor/org.joor.Reflect.on(Reflect.java:896)
at org.jooq.joor/org.joor.Reflect.call(Reflect.java:563)
at org.jooq.joor/org.joor.Reflect.call(Reflect.java:516)
at io.github.sskorol.reflection/io.github.sskorol.reflection.testcases.ReflectionTests.lambda$shouldAccessAnnotationValues$5(ReflectionTests.java:27)
at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:195)
at java.base/java.util.stream.SortedOps$SizedRefSortingSink.end(SortedOps.java:361)
at java.base/java.util.stream.StreamSpliterators$AbstractWrappingSpliterator.fillBuffer(StreamSpliterators.java:210)
at java.base/java.util.stream.StreamSpliterators$AbstractWrappingSpliterator.doAdvance(StreamSpliterators.java:161)
at java.base/java.util.stream.StreamSpliterators$WrappingSpliterator.tryAdvance(StreamSpliterators.java:300)
at java.base/java.util.stream.ReferencePipeline$7$1.accept(ReferencePipeline.java:278)
at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:195)
at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:195)
at java.base/java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:177)
at java.base/java.util.Spliterators$ArraySpliterator.tryAdvance(Spliterators.java:958)
at java.base/java.util.stream.ReferencePipeline$7$1.accept(ReferencePipeline.java:278)
at java.base/java.util.stream.WhileOps$1$1.accept(WhileOps.java:99)
at one.util.streamex@0.7.0/one.util.streamex.StreamEx$2.tryAdvance(StreamEx.java:2741)
at java.base/java.util.stream.ReferencePipeline.forEachWithCancel(ReferencePipeline.java:127)
at java.base/java.util.stream.AbstractPipeline.copyIntoWithCancel(AbstractPipeline.java:502)
at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:488)
at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:474)
at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:550)
at java.base/java.util.stream.AbstractPipeline.evaluateToArrayNode(AbstractPipeline.java:260)
at java.base/java.util.stream.ReferencePipeline.toArray(ReferencePipeline.java:517)
at one.util.streamex@0.7.0/one.util.streamex.AbstractStreamEx.toArray(AbstractStreamEx.java:344)
at one.util.streamex@0.7.0/one.util.streamex.AbstractStreamEx.toList(AbstractStreamEx.java:1186)
at io.github.sskorol.reflection/io.github.sskorol.reflection.testcases.ReflectionTests.shouldAccessAnnotationValues(ReflectionTests.java:28)
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.testng@7.0.0/org.testng.internal.MethodInvocationHelper.invokeMethod(MethodInvocationHelper.java:133)
at org.testng@7.0.0/org.testng.internal.TestInvoker.invokeMethod(TestInvoker.java:584)
at org.testng@7.0.0/org.testng.internal.TestInvoker.invokeTestMethod(TestInvoker.java:172)
at org.testng@7.0.0/org.testng.internal.MethodRunner.runInSequence(MethodRunner.java:46)
at org.testng@7.0.0/org.testng.internal.TestInvoker$MethodInvocationAgent.invoke(TestInvoker.java:804)
at org.testng@7.0.0/org.testng.internal.TestInvoker.invokeTestMethods(TestInvoker.java:145)
at org.testng@7.0.0/org.testng.internal.TestMethodWorker.invokeTestMethods(TestMethodWorker.java:146)
at org.testng@7.0.0/org.testng.internal.TestMethodWorker.run(TestMethodWorker.java:128)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1540)
at org.testng@7.0.0/org.testng.TestRunner.privateRun(TestRunner.java:770)
at org.testng@7.0.0/org.testng.TestRunner.run(TestRunner.java:591)
at org.testng@7.0.0/org.testng.SuiteRunner.runTest(SuiteRunner.java:402)
at org.testng@7.0.0/org.testng.SuiteRunner.runSequentially(SuiteRunner.java:396)
at org.testng@7.0.0/org.testng.SuiteRunner.privateRun(SuiteRunner.java:355)
at org.testng@7.0.0/org.testng.SuiteRunner.run(SuiteRunner.java:304)
at org.testng@7.0.0/org.testng.SuiteRunnerWorker.runSuite(SuiteRunnerWorker.java:53)
at org.testng@7.0.0/org.testng.SuiteRunnerWorker.run(SuiteRunnerWorker.java:96)
at org.testng@7.0.0/org.testng.TestNG.runSuitesSequentially(TestNG.java:1180)
at org.testng@7.0.0/org.testng.TestNG.runSuitesLocally(TestNG.java:1102)
at org.testng@7.0.0/org.testng.TestNG.runSuites(TestNG.java:1032)
at org.testng@7.0.0/org.testng.TestNG.run(TestNG.java:1000)
at org.gradle.api.internal.tasks.testing.testng.TestNGTestClassProcessor.runTests(TestNGTestClassProcessor.java:141)
at org.gradle.api.internal.tasks.testing.testng.TestNGTestClassProcessor.stop(TestNGTestClassProcessor.java:90)
at org.gradle.api.internal.tasks.testing.SuiteTestClassProcessor.stop(SuiteTestClassProcessor.java:61)
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:36)
at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
at org.gradle.internal.dispatch.ContextClassLoaderDispatch.dispatch(ContextClassLoaderDispatch.java:33)
at org.gradle.internal.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:94)
at com.sun.proxy.$Proxy2.stop(Unknown Source)
at org.gradle.api.internal.tasks.testing.worker.TestWorker.stop(TestWorker.java:132)
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:36)
at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
at org.gradle.internal.remote.internal.hub.MessageHubBackedObjectConnection$DispatchWrapper.dispatch(MessageHubBackedObjectConnection.java:182)
at org.gradle.internal.remote.internal.hub.MessageHubBackedObjectConnection$DispatchWrapper.dispatch(MessageHubBackedObjectConnection.java:164)
at org.gradle.internal.remote.internal.hub.MessageHub$Handler.run(MessageHub.java:412)
at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:64)
at org.gradle.internal.concurrent.ManagedExecutorImpl$1.run(ManagedExecutorImpl.java:48)
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:56)
at java.base/java.lang.Thread.run(Thread.java:834)
Caused by: java.lang.IllegalAccessException: class org.joor.Reflect (in module org.jooq.joor) cannot access class com.sun.proxy.jdk.proxy2.$Proxy9 (in module jdk.proxy2) because module jdk.proxy2 does not export com.sun.proxy.jdk.proxy2 to module org.jooq.joor
at java.base/jdk.internal.reflect.Reflection.newIllegalAccessException(Reflection.java:361)
at java.base/java.lang.reflect.AccessibleObject.checkAccess(AccessibleObject.java:591)
at java.base/java.lang.reflect.Method.invoke(Method.java:558)
at org.jooq.joor/org.joor.Reflect.on(Reflect.java:892)
... 79 more
我创建了一个sample project来重现该问题(仅那些在注释方法调用失败的部分)。
似乎应该在Gradle配置中打开/导出某些JDK内部组件。如果您能指出解决此问题的确切原因,将不胜感激。
更新:
以下是关键代码段:
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.TYPE})
public @interface Find {
By by();
String locator();
String name() default "";
}
public class LoginPage {
@Find(by = By.CSS, locator = "[data-qa=username]", name = "username input")
private Input username;
}
var values = StreamEx.iterate(LoginPage.class, (UnaryOperator<Class<?>>) Class::getSuperclass)
.takeWhile(page -> !page.equals(Object.class))
.flatMap(page -> stream(page.getDeclaredFields()))
.filter(field -> field.isAnnotationPresent(Find.class))
.map(field -> field.getAnnotation(Find.class))
.flatMap(annotation -> StreamEx.of(annotation.annotationType().getDeclaredMethods())
.sortedBy(Method::getName)
.map(method -> on(annotation).call(method.getName()).get()))
.toList();
这是jOOR的一个序列(当call
方法被调用时-> on(annotation).call(method.getName()).get()
):