处理 AOP 反射代理:"object is not an instance of declaring class"

Handling AOP reflective proxies: "object is not an instance of declaring class"

我的应用程序需要对 Spring bean 执行动态调用。我扫描一个 Spring bean 以查找使用自定义注释注释的方法,并存储对 Method object 的引用以供将来调用。

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 个事务。

我使用以下代码获取 clazz 变量,因为 AOP 代理不显示来自源 class

的注释
    Class<?> managerClass;
    if (workflowManager instanceof TargetClassAware)
        managerClass = ((TargetClassAware) workflowManager).getTargetClass();
    else
        managerClass = workflowManager.getClass();

总而言之,我需要使用 TargetClassAware,否则我将无法扫描注释,但如果我从原始 class 获得方法,它将与代理 class.

如何正确调用方法?

在我写问题的过程中,我自己找到了答案。

我的想法是对的:我不能扫描AOP代理,否则我不能得到注解,但是我必须选择不是来自原始class 而是来自代理的方法本身.

方法如下:扫描目标 class 以查找带注释的方法,然后从代理 class 中选择相同的方法(相同的名称和参数)。代码有两种修改方式,这里是一种:

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;
}

也可以修改代码以从 getMethod 中检查 TargetClassAware,而无需使用 2 个参数