下面是我的代码示例:
class foo extends afoo{
@HTTPPost
returnClass runTransaction(RequestData req){
return sendData(req, returnClass.class)
}
@HTTPGet
returnClass runTransaction2(RequestData req){
return sendData(req, returnClass.class)
}
}
abstract class afoo {
public <T> T sendData(ARestMessage req, Class<T> returnClassType)
//here i need the annotation of the calling method
}
基本上,我正在构建一个非常复杂的消息传递系统,我想尽可能多地将切换和配置放在注释中。
是的,我知道有一些库(比如谷歌反射)会让这件事变得更容易,但为了让我使用它们,我必须做4-6个月的文书工作,并与企业架构部门会面,以获得使用它们的批准。看到这个项目必须在两个月内完成,我正在手工做。
因此,我所做的是创建注释,开发人员可以通过指示生成的服务期望发送数据的方式来对方法进行注释。这可能是一个get、post、put等。在抽象类中,所有服务类都扩展了一个senddata方法。该方法必须能够确定是哪种方法用于调用它,也就是说,是由runTransaction还是runTransaction2调用的,所以sendData会拉取该方法的注释,从而确切地知道如何将数据发送到服务。
现在我发现了这个(这是我sendData方法中的第一行代码)
final Method callingMethod = this.getClass().getEnclosingMethod();
但它一直返回null。我已经读了好几次关于它的javadoc,我不明白为什么它总是返回null。
我知道我可以使用堆栈来获得父调用程序,但我不希望这样做,因为这个应用程序与另一个执行大量AOP工作的应用程序共享应用程序服务器内存。AOP的工作非常擅长以意想不到的方式扰乱堆栈,所以我宁愿使用直接反射来解决这个问题。
有人知道为什么这个方法一直返回null吗?是因为它包含在一个抽象类中,而不是我的foo类本身吗?有没有一种方法可以使用我喜欢使用的技术来实现这一点?
感谢
方法Class.getEnclosingMethod()
不会执行您认为它会执行的操作。这是它的Javadoc:
如果此Class对象表示方法,返回一个表示立即封闭的method对象基础类的方法否则返回null。特别地,如果基础类是本地或立即由类型声明、实例括起来的匿名类初始化器或静态初始化器。
具体来说,它返回匿名内部类的外部封闭方法,该方法是在该方法的上下文中定义的。在您的描述中,我没有看到这些消息传递方法是从匿名/本地内部类调用的。以下是代码中的一个示例(需要jUnit):
import java.lang.reflect.Method;
import org.junit.Assert;
import org.junit.Test;
interface Introspector {
public Method getEnclosingMethod();
}
public class Encloser {
public Encloser() {
super();
}
public Method noop() {
final Introspector inner = new Introspector() {
@Override
public Method getEnclosingMethod() {
return getClass().getEnclosingMethod();
}
};
return inner.getEnclosingMethod();
}
@Test
public void testEnclosingMethods() throws Exception {
final Encloser encloser = new Encloser();
Method method = encloser.getClass().getEnclosingMethod();
Assert.assertNull(method);
method = encloser.noop();
Assert.assertNotNull(method);
}
}
您当前的解决方案听起来相当复杂。您是否计划在方法调用链上走一走(只能通过转储stacktrace btw来完成),并在进行一些大量反射后寻找注释?我预见会有很多虫子。坦率地说,采用某种构建器模式可能更适合您的场景。
这里使用注释没有意义,只需将另一个参数传递给方法sendData()
即可。