Reputation: 1925
Spring 3.2. Everything works when I do:
@Controller
public class MyController {
@Inject
Provider<MyBean> provider;
@RequestMapping("/chart")
public void getChart(HttpServletResponse resp) {
provider.get();
}
}
but it doesn't work when I set MyBean as an argument to getChart:
@Controller
public class MyController {
@RequestMapping("/chart")
public void getChart(HttpServletResponse resp, MyBean myBean) {
// No such method MyBean.<init>()
}
}
So Spring tries to create a new instance of myBean instead of using already bound one.
Configuration:
@Configuration
public class Config {
@Inject
@Bean @Scope("request")
public MyBean provideMyBean(MyOtherBean myOtherBean) {
return myOtherBean.getMyBean();
}
}
It also doesn't work if I make my controller request scoped, and add @Inject/@Autowired to the getChart()
. Then it cannot find HttpServletResponse instance (NoSuchBeanDefinitionException), although there surely must be one in request-scope.
Maybe it just isn't implemented in Spring?
Upvotes: 5
Views: 3540
Reputation: 1925
Resolved by creating a custom 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);
}
}
and in 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;
}
Upvotes: 1