1. 程式人生 > 其它 >無法獲取cglib代理物件上的註解的解決辦法

無法獲取cglib代理物件上的註解的解決辦法

前言

開發程式的時候使用了aop去代理物件,然後其他地方會獲取到這個代理物件並獲取上面的方法註解和引數註解,執行時卻發現無法獲取註解,最終折騰一番終於解決。

原因

使用了AOP去進行代理,由於代理的物件不是介面,因此springboot會使用cglib去進行代理。
debug的時候可以看到,代理物件是由cglib代理的。

然後遍歷bean這個類的方法,依次獲取方法上的MessageMapping註解,獲取到就將其新增到map中
這裡獲取註解的方法是AnnotatedElementUtils.getMergedAnnotation()
但是,發現本應能獲取到註解的方法,此時卻無法獲取到註解
通過debug繼續檢視下去,發現方法上的註解全部為空

獲取方法上的註解

其實解決辦法非常簡單,只需要將上面獲取註解的程式碼AnnotatedElementUtils.getMergedAnnotation()改為AnnotatedElementUtils.findMergedAnnotation()就能輕鬆解決
可以看到,通過這種方式可以成功獲取到方法上的註解,並且進入了if判斷

獲取方法引數上的註解

隨後需要獲取方法引數上的註解,同樣也是獲取為null

這個問題是比較棘手,試過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);