4

春天 3.2。当我这样做时一切正常:

@Controller
public class MyController {
    @Inject
    Provider<MyBean> provider;

    @RequestMapping("/chart")
    public void getChart(HttpServletResponse resp) {
        provider.get();
    }
}

但是当我将 MyBean 设置为 getChart 的参数时它不起作用:

@Controller
public class MyController {

    @RequestMapping("/chart")
    public void getChart(HttpServletResponse resp, MyBean myBean) {
        // No such method MyBean.<init>()
    }
}

所以 Spring 尝试创建一个新的 myBean 实例,而不是使用已经绑定的实例。

配置:

@Configuration
public class Config {
    @Inject
    @Bean @Scope("request")
    public MyBean provideMyBean(MyOtherBean myOtherBean) {
         return myOtherBean.getMyBean();
    }
}

如果我将控制器请求设置为范围,并将 @Inject/@Autowired 添加到getChart(). 然后它找不到 HttpServletResponse 实例 (NoSuchBeanDefinitionException),尽管在请求范围内肯定有一个。

也许它只是没有在 Spring 中实现?

4

1 回答 1

1

通过创建自定义 HandlerMethodArgumentResolver 解决:

/**
 * Resolves beans defined in {@link Config},
 * because Spring doesn't want to do it implicitly.
 *
 * Makes possible to write something like
 * @RequestMapping(value="/chart", method=RequestMethod.GET)
 * getChart(HttpServletRequest req, MyBean myBean)
 *
 * and Spring will inject both arguments.
 */
public class MethodArgumentResolver implements HandlerMethodArgumentResolver, BeanFactoryAware {
    private final Set<Class> knownTypes = Config.getDeclaredTypes();

    private BeanFactory beanFactory;

    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        this.beanFactory = beanFactory;
    }

    @Override
    public boolean supportsParameter(MethodParameter parameter) {
        Class<?> type = parameter.getParameterType();
        return knownTypes.contains(type);
    }

    @Override
    public Object resolveArgument(
            MethodParameter parameter,
            ModelAndViewContainer mavContainer,
            NativeWebRequest webRequest,
            WebDataBinderFactory binderFactory) throws Exception {
        Class<?> type = parameter.getParameterType();
        return beanFactory.getBean(type);
    }
}

在配置中:

static Set<Class> getDeclaredTypes() {
    Set<Class> result = Sets.newHashSet();
    Method[] methods = Config.class.getDeclaredMethods();
    for (Method method : methods) {
        if (method.getAnnotation(Bean.class) != null) {
            result.add(method.getReturnType());
        }
    }
    return result;
}
于 2013-06-17T04:32:21.470 回答