我正在使用jdk1.8.0_221
我想根据调用两种不同类型的方法在父类(super class)的构造函数中加载特定配置。我正在寻找最佳实践,最好是一种方便的方法。
为了简化,我将代码情况模拟如下:
package test;
public class A extends Z{
@Test
@Marker1
public void f1() {
Z.g();
}
@Test
@Marker2
public void f2() {
Z.g();
}
}
package test;
public class B extends Z{
@Test
@Marker1
public void f3() {
Z.g();
}
@Test
@Marker2
public void f4() {
Z.g();
}
}
package core;
public class Z{
public Z() {
//I want to determine here that which type of method calls this constructor
//The caller could be Marker1 or Marker2
//And based on the caller, load the corresponding configuration
}
public static void g(){
//some code goes here
}
}
注意1:来自不同类的许多方法调用 Z.g()
,所以我无法使用类的显式名称来获取方法及其注释。
注意2:所有配置都应该在Z的父类(super class)的构造函数中完成。
注3:g()
方法不一定是静态的。
我尝试过以下代码片段,但是 getMethodName()
始终返回<init>
:
public Z() throws NoSuchMethodException, ClassNotFoundException{
StackTraceElement[] stElements = Thread.currentThread().getStackTrace();
StackTraceElement ste = stElements[3];// or stElements[2]
Class<?> aClass = Class.forName(ste.getClassName());
String methodName = ste.getMethodName();
Method method = aClass.getMethod(methodName);
Annotation[] annotations = aClass.getAnnotations();
for (Annotation annotation : annotations) {
if (annotation.getClass().equals(Marker1.class)) {
//load conf1
break;
} else if (annotation.getClass().equals(Marker2.class)) {
//load conf2
break;
}
}
}
此外,我在 stackoverflow 和其他社区尝试了很多解决方案,但都无法正常工作。
最佳答案
你得到的结果,准确地告诉你发生了什么。您的方法都没有调用构造函数。
所有方法都具有以下形式
@Test
@MarkerN
public void fX() {
Z.g();
}
因此它们包含对 static
的调用方法g()
类Z
。但没有实例化 Z
.
相反,您的类(class) A
和B
是 Z
的子类。由于您没有为它们声明显式构造函数,因此编译器会为它们生成默认构造函数,例如
public class A extends Z {
public A() {
super(); // here, the constructor of Z gets called
}
// the other methods …
}
因此,反射查找将告诉您 Z
的调用的构造函数发生在名为 <init>
的方法内,即A
的构造函数,分别是B
B
的构造函数.
如果这些方法这样做的话,情况会有所不同new Z().g()
,但这会使依赖于 static
之前执行的构造函数的设计变得可疑。方法调用更糟。
这个问题应该在框架端解决,框架端同时执行这两个操作,实例化 A
和B
并调用方法 f1()
至f4()
在他们。例如。使用 JUnit 5,解决方案如下所示:
package test;
import java.lang.annotation.*;
import java.lang.reflect.AnnotatedElement;
import org.junit.jupiter.api.*;
public class A {
@BeforeEach
public void prepare(TestInfo ti) {
Z.loadConfiguration(ti.getTestMethod().get());
}
@Test
@Marker1
public void f1() {
Z.g();
}
@Test
@Marker2
public void f2() {
Z.g();
}
}
class Z {
public static void loadConfiguration(AnnotatedElement e) {
if(e.isAnnotationPresent(Marker1.class)) {
System.out.println("Marker1");
}
else if(e.isAnnotationPresent(Marker2.class)) {
System.out.println("Marker2");
}
}
public static void g() {
System.out.println("Z.g()");
}
}
@Retention(RetentionPolicy.RUNTIME)
@interface Marker1 {}
@Retention(RetentionPolicy.RUNTIME)
@interface Marker2 {}
Marker1
Z.g()
Marker2
Z.g()
关于java - 如何从另一个类获取调用者方法的注释,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58040218/