Loading

无法获取cglib代理对象上的注解的解决办法

前言

开发程序的时候使用了aop去代理对象,然后其他地方会获取到这个代理对象并获取上面的方法注解和参数注解,运行时却发现无法获取注解,最终折腾一番终于解决。

原因

使用了AOP去进行代理,由于代理的对象不是接口,因此springboot会使用cglib去进行代理。
debug的时候可以看到,代理对象是由cglib代理的。
image
然后遍历bean这个类的方法,依次获取方法上的MessageMapping注解,获取到就将其添加到map中
这里获取注解的方法是AnnotatedElementUtils.getMergedAnnotation()
但是,发现本应能获取到注解的方法,此时却无法获取到注解
通过debug继续查看下去,发现方法上的注解全部为空
image

获取方法上的注解

其实解决办法非常简单,只需要将上面获取注解的代码AnnotatedElementUtils.getMergedAnnotation()改为AnnotatedElementUtils.findMergedAnnotation()就能轻松解决
可以看到,通过这种方式可以成功获取到方法上的注解,并且进入了if判断
image

获取方法参数上的注解

随后需要获取方法参数上的注解,同样也是获取为null
image

这个问题是比较棘手,试过SpringBoot内置的工具类,目前没找到能正常获取注解的方式。
因此决定换个思路,直接获取cglib代理类的原始对象,获取原始对象上的参数注解就可以了
直接上代码

private Parameter getProxySourceMethodParameter(Class<?> clazz, Method method, Integer parameterIndex) throws NoSuchFieldException, IllegalAccessException, NoSuchMethodException {
    boolean isCglibProxyClass = clazz.getName().contains("$$");
    if (!isCglibProxyClass) {
        return ArrayUtil.get(method.getParameters(), parameterIndex);
    }
    Class<?> sourceClass = clazz.getSuperclass();
    String methodName = method.getName();
    Class<?>[] methodParameterTypes = method.getParameterTypes();
    Method sourceMethod = sourceClass.getDeclaredMethod(methodName, methodParameterTypes);
    return ArrayUtil.get(sourceMethod.getParameters(), parameterIndex);
}

通过获取原始类的方法参数,然后再获取参数上的注解就可以解决了。

Parameter parameter = getProxySourceMethodParameter(clazz, method, paramIndex);
Ref ref = AnnotatedElementUtils.findMergedAnnotation(parameter, Ref.class);
posted @ 2022-04-15 21:51  马卡龙MK  阅读(1098)  评论(0编辑  收藏  举报