我需要实现与 @RequestParam("foo")
相同的行为但在 REQUEST
的构造函数中作用域 bean,其中其他构造函数参数将正常 Autowiring 。
我希望在构造函数中注入(inject)一个请求参数,就像它是一个普通的 bean 一样,但显然实际上并不是一个 spring bean。
示例:
@Component
@RequestScope
public class RequestBean {
private final String filter;
private final UserRepository userRepository;
public RequestBean(@Param("filter") String filter, UserRepository userRepository) {
this.filter = filter;
this.userRepository = userRepository;
}
...
}
我尝试使用 BeanFactoryPostProcessor,但我需要注入(inject)的值必须在请求时获取,而不是在 bean 定义时获取。
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
Stream.of(beanFactory.getBeanDefinitionNames())
.map(name -> beanFactory.getBeanDefinition(name))
.filter(def -> "request".equals(def.getScope()))
.forEach(beanDefinition -> {
try {
System.out.println(beanDefinition);
for (Constructor<?> constructor : Class.forName(beanDefinition.getBeanClassName()).getConstructors()) {
for (Parameter parameter : constructor.getParameters()) {
Param param = parameter.getAnnotation(Param.class);
if(param != null) {
String paramName = param.value(); // filter
Object requestParameterValue = "request.getParameter('" + paramName + "')"; // bean creation time evaluated argument
beanDefinition.getConstructorArgumentValues().addGenericArgumentValue(
new ConstructorArgumentValues.ValueHolder(requestParameterValue, parameter.getType().getName(), parameter.getName())
);
}
}
}
} catch (Exception ex) {
// whatever
}
});
}
}
对于 /index?filter=blue
的请求我希望“blue”和 userRepository 被自动连接。
如果我尝试使用固定值,它会完美工作,该值和另一个 bean 会正常自动连接。
我无法使用BeanPostProcessor
因为必须在实例化(构造函数注入(inject))之前获取值
最佳答案
终于,我找到了实现我想要的目标的方法。
我定义了一个REQUEST
范围来简化获取和转换请求参数的过程。
由于 BeanFactoryPostProcessor 中注册的表达式 (SprEL),该 Bean 将在创建时被调用。
将计算表达式并将返回值注入(inject)带注释的参数中。
这会将动态表达式添加到构造函数参数中:
String name = param.value();
TypedStringValue dynamicValue = new TypedStringValue("#{@myBean.getParameter('"+name+"')}");
beanDefinition.getConstructorArgumentValues().addIndexedArgumentValue(index, dynamicValue, constructorParameter.getType().getName());
这是在带注释的 bean 实例化之前由表达式调用的 bean:
@Component
@RequestScope
class MyBean {
final HttpServletRequest request;
public MyBean(HttpServletRequest request) {
this.request = request;
}
public String getParameter(String name){
// do something
return request.getParameter(name);
}
}
关于java - 在实例化之前,在 spring bean Autowiring 构造函数中自定义参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40726013/