java - 在实例化之前,在 spring bean Autowiring 构造函数中自定义参数

标签 java spring spring-mvc

我需要实现与 @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/

相关文章:

java - 如何在 java 中将 HashMap 的键视为可选

java - list 合并失败并出现多个错误,请参阅 Android Studio 上的日志

java - @Value 注解不从属性文件中注入(inject)值

java - 带数组的字符串输入

java - 来自 Spring RestClient 和 Jackson 的嵌套 JSON 对象

java - 如何将同一个bean实例注入(inject)到多个bean中

Spring 或 Spring Boot

spring-mvc - Extjs 4 MVC - App.JS 找到我的 Controller 的相对路径问题 - 在带有 Spring MVC 的 WEB-INF 下

spring - 我想获得有关 Spring BeanCreationException 错误的建议

java - 如何将 JAVA Swing 中的时间转换为货币