gpt4 book ai didi

java - 为什么我无法从已加载的 Java 类中检测到注释?

转载 作者:塔克拉玛干 更新时间:2023-11-02 08:03:54 24 4
gpt4 key购买 nike

我有一个插件,我想从我的 Maven 项目访问我的模型包的类列表。直到现在我只是这样做来将类加载到插件中:

try {
runtimeClasspathElements = project.getRuntimeClasspathElements();

} catch (DependencyResolutionRequiredException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
URL[] runtimeUrls = new URL[runtimeClasspathElements.size()];
for (int i = 0; i < runtimeClasspathElements.size(); i++) {
String element = (String) runtimeClasspathElements.get(i);
try {
runtimeUrls[i] = new File(element).toURI().toURL();
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

newLoader = new URLClassLoader(runtimeUrls,
Thread.currentThread().getContextClassLoader());
try { class=newLoader.loadClass("com.pkl.bc.personnaldata.model.Personne");

if(class!=null)
System.out.println(class.getCanonicalName());
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

直到这里我才能看到我类(class)的全名。

System.out.println(class.getDeclaredFields());
System.out.println(class.isAnnotationPresent(EditColumn.class));
for (Field f : class.getDeclaredFields()) {

EditColumn v = f.getAnnotation(EditColumn.class);
if (v != null) {

System.out.println(v.tableName());
System.out.println(v.oldName());

}

}

但我什么也没得到,这是输出:

[Ljava.lang.reflect.Field;@398f573b
false

我也尝试过使用反射

Reflections reflections = new Reflections("com.pkl.bc.personnaldata.model.Personne");

Set<Field> annotated = reflections.getFieldsAnnotatedWith(EditColumn.class);

System.out.println(annotated);

这给了我一个空列表。这是我的注释:

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD})
public @interface EditColumn {

String oldName() default "";

String newName() default "";

String tableName() default "";
}

注释字段:

@EditColumn(newName = "main_adress", oldName = "adress", tableName = "Personne")
private String main_adress;

最佳答案

我修正了我的答案,当 Thread.getContextClassLoader() 返回 null 时,你的问题是在不同的 ClassLoader 中加载不同的类实例,因为 URLClassLoader(urls,parent) 当parent 为 null。你可以看到 java 两种方式都为 Annotation Name 实例返回 Proxy 实例的测试。经常有人调用 Thread.currentThread() 时会出现此问题.setContextClassLoader(null) 在某处。所以你可以通过检查contextLoader是否为null来解决问题。例如:

ClassLoader context=Thread.currentThread().getContextClassLoader();
if(context==null){
context=getClass().getClassLoader();
}
URLClassLoader loader=new URLClassLoader(urls,context);

测试

import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

import java.lang.annotation.Annotation;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.HashSet;
import java.util.Objects;
import java.util.Set;
import java.util.function.Consumer;
import java.util.stream.Stream;

import static java.lang.String.format;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.*;

/**
* Created by holi on 3/24/17.
*/
public class AnnotationsTest {
private interface StubClass {
Class<?> stubClass() throws ClassNotFoundException;

default <T extends Annotation> T annotation(Class<T> type) throws Exception {
return stubClass().getAnnotation(type);
}

default Annotation[] annotations() throws Exception {
return stubClass().getAnnotations();
}
}

private static final StubClass JAR_WITHIN_ANNOTATION_CLASS = jar("stubs-within-annotation-class.jar");
private static final StubClass JAR_WITHOUT_ANNOTATION_CLASS = jar("stubs-without-annotation-class.jar");

public static StubClass jar(String jar) {
URL jarFile = Objects.requireNonNull(ClassLoader.getSystemResource(jar), format("Jar file not found:%s", jar));
return () -> {
ClassLoader context = Thread.currentThread().getContextClassLoader();
return new URLClassLoader(new URL[]{jarFile}, context).loadClass("Stub");
};
}

private ClassLoader original;

@BeforeEach
void setUp() throws Throwable {
original = Thread.currentThread().getContextClassLoader();
}

@AfterEach
void tearDown() throws Throwable {
Thread.currentThread().setContextClassLoader(original);
}

@Test
void getAnnotationFromJarClassesWillReturnsContextLoaderAnnotationSharedInstanceIfContextLoaderAssociatedWithRuntimeClassLoader() throws Throwable {
Set<Object> annotationsCreated = new HashSet<>();
Set<Object> stubClassCreated = new HashSet<>();
Thread.currentThread().setContextClassLoader(getClass().getClassLoader());

Stream.of(JAR_WITHIN_ANNOTATION_CLASS, JAR_WITHOUT_ANNOTATION_CLASS).forEach(asserts(stub -> {
Name it = stub.annotation(Name.class);
assertThat(it, is(instanceOf(Name.class)));
assertThat(it.value(), equalTo("stub"));
annotationsCreated.add(it);
stubClassCreated.add(stub.stubClass());
}));

assertThat(annotationsCreated, hasSize(1));
assertThat(stubClassCreated, hasSize(2));
}

@Test
void getAnnotationFromJarClassesWillReturnsNullIfNoContextLoaderAssociated() throws Throwable {
Thread.currentThread().setContextClassLoader(null);

Stream.of(JAR_WITHIN_ANNOTATION_CLASS, JAR_WITHOUT_ANNOTATION_CLASS).forEach(asserts(it -> {
//create different class instance in each class loader
assertThat(it.stubClass().getName(), equalTo("Stub"));

assertThat(it.annotation(Name.class), is(nullValue()));
}));

assertThat(JAR_WITHOUT_ANNOTATION_CLASS.annotations(), is(emptyArray()));
assertThat(JAR_WITHIN_ANNOTATION_CLASS.annotations(), arrayWithSize(1));
Annotation it = JAR_WITHIN_ANNOTATION_CLASS.annotations()[0];

assertThat(it.annotationType(), is(not(instanceOf(Name.class))));
assertThat(it.annotationType().getName(), equalTo(Name.class.getName()));
assertThat(it.annotationType().getDeclaredMethod("value").invoke(it), equalTo("stub"));
}


private interface Assert<T> {
void assertThat(T value) throws Exception;
}

private <T> Consumer<T> asserts(Assert<T> executor) {
return (value) -> {
try {
executor.assertThat(value);
} catch (RuntimeException e) {
throw e;
} catch (Exception e) {
RuntimeException wrappedException = new RuntimeException(e);
wrappedException.setStackTrace(e.getStackTrace());
throw wrappedException;
}
};
}
}

@Name注解

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

/**
* Created by holi on 3/24/17.
*/
@Retention(RetentionPolicy.RUNTIME)
public @interface Name {
String value();
}

stub 类

@Name("stub")
public class Stub{
}

关于java - 为什么我无法从已加载的 Java 类中检测到注释?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42994838/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com