找不到获取 Spring Bean 的方法参数的参数化类型的方法



我需要能够在Spring bean上找到方法参数的参数化类型。

我正在使用 Spring Boot 2.0.1。

我有一个春豆,看起来像下面:

public class MyBean {
public void doFoo(List<Integer> param) {...}
}

我需要能够找出param参数的参数化类型。 通常我可以这样做:

MyBean myBean = getMyBean();
ParameterizedType pt = (ParameterizedType)myBean
.getClass()
.getMethod("doFoo", List.class)
.getGenericParameterTypes()[0];
Class<?> listOfX = (Class<?>)pt.getActualTypeArguments()[0];

但是,当对 Spring Bean 执行此操作时,getGenericParameterTypes()方法始终返回一个Class对象的数组,而不是一个Type对象的数组。

原因是 Spring 广泛使用 CGLIB 来提供类的运行时重新编译以支持 AOP。 因此,我没有获得MyBean的实例,而是获得了MyBean$$EnhancerBySpringCGLIB$$xxxxxxxx的实例,并且该"重新编译"的类丢失了所有泛型信息(显然是因为CGLIB是在泛型存在之前编写的,并且不再受到积极支持?

我可以使用一些想法来了解如何获取有关此参数的参数化信息,如果只给出一个 Spring bean 实例。 我一直在努力寻找从MyBean$$EnhancerBySpringCGLIB$$xxxxxxxx访问MyBean.class的方法,并从那里找到我可以使用反射的真正方法。 但我还没有找到解决方案。 我试图不惜一切代价避免Class.forName(...)

一种可能的解决方案是实现BeanPostProcessor。 您可以在 Bean 初始化之前访问底层类。

这里的例子:

@Component
public class ParametrizedBeanFactoryPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
// bean is your actual class
try {
if ("myBean".equals(beanName)) {
ParameterizedType pt = (ParameterizedType) bean
.getClass()
.getMethod("doFoo", List.class)
.getGenericParameterTypes()[0];
Class<?> listOfX = (Class<?>) pt.getActualTypeArguments()[0];
System.out.println(listOfX); //class java.lang.Integer
}
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
// bean is proxy object
return bean;
}
}

看起来以下代码在我的特定情况下可以找到底层的真实类:

if (myBean instanceof org.springframework.aop.framework.Advised) {
Class<?> realClass = ((Advised)r).getTargetClass();
}

从那里我可以使用标准反射。 但我不确定这个解决方案的犹太洁食程度如何,或者我是否可以期望所有 Spring bean 都实现Advised接口。

最新更新