我的应用程序需要在Spring bean上执行动态调用。我扫描Spring bean以获取使用自定义注释注释的方法,并将对Method
对象的引用存储起来以供将来调用。
public Method getMethod(Class<?> clazz, final String name) throws ReflectiveOperationException, NoSuchMethodException
{
Method meth = null;
for (Method m : clazz.getMethods())
{
String alias;
WorkflowMethod annotation = m.getAnnotation(WorkflowMethod.class);
if (annotation == null)
{
log.warn(...);
continue;
}
alias = annotation.alias();
if (StringUtils.isEmpty(alias))
alias = m.getName();
if (!name.equals(alias))
continue;
if (meth != null)
throw new Exception(...);
meth = m;
}
if (meth == null)
throw new NoSuchMethodException(...);
return meth;
}
上面的代码将根据它没有重载的事实(按要求)按名称提取方法。
但是,当我稍后在代码中尝试调用meth.invoke(springBean,params)
时,我会在标题中获得InvocationTargetException
描述。
我所有的bean都是AOP代理,因为我使用的是Spring Transactions。
我使用以下代码获取clazz
变量,因为AOP代理不会显示来自源类的注释
Class<?> managerClass;
if (workflowManager instanceof TargetClassAware)
managerClass = ((TargetClassAware) workflowManager).getTargetClass();
else
managerClass = workflowManager.getClass();
总结一下,我需要使用TargetClassAware
,否则我将无法扫描注释,但如果我从原始类中获取方法,则它将与代理类不兼容。
如何正确调用方法?
答案 0 :(得分:0)
在我写这个问题时,我自己找到了答案。
我的想法是对的:我无法扫描AOP代理,否则我无法获得注释,但是我必须选择的方法不是来自原始类,而是来自代理本身。
方法如下:扫描目标类以获取带注释的方法,然后从代理类中选择相同的方法(相同的名称和参数)。代码可以通过两种方式修改,这里有一个:
public Method getMethod(Class<?> targetClass, Class<?> proxyClass, final String name) throws ReflectiveOperationException, NoSuchMethodException
{
Method meth = null;
for (Method m : targetClass.getMethods())
{
String alias;
WorkflowMethod annotation = m.getAnnotation(WorkflowMethod.class);
if (annotation == null)
{
log.warn("...);
continue;
}
alias = annotation.alias();
if (StringUtils.isEmpty(alias))
alias = m.getName();
if (!name.equals(alias))
continue;
if (meth != null)
throw new Exception(...);
if (proxyClass == null)
meth = m;
else
meth = proxyClass.getMethod(m.getName(), m.getParameterTypes());
}
if (meth == null)
throw new NoSuchMethodException(...);
return meth;
}
也可以修改代码以在TargetClassAware
内检查getMethod
,而无需使用2个参数