春天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中没有实现?
答案 0 :(得分: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);
}
}
并在Config中:
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;
}