原型Bean内部Autowired注入Customer失败,报空指针问题求助
为什么@Autowired没法给Customer注入引用?
咱们先揪出问题的核心:你手里的ServiceImpl实例根本不是Spring容器管理的对象,所以Spring不会帮它处理@Autowired注入。
具体原因分析
你的MyController里的post(ServiceImpl impl)方法,这里的impl参数是Spring MVC通过请求数据绑定机制直接new出来的,完全和你用@Component标记的原型Bean没关系。
Spring只会对自己容器里创建管理的Bean执行依赖注入,这种“外部”new出来的对象,Spring根本不会管它的@Autowired注解,所以Customer c自然就是null,调用c.getName()就会触发空指针异常。
另外补充下:哪怕ServiceImpl是原型作用域的Bean,你也得通过Spring容器去获取它的实例,而不是靠方法参数这种方式。
两种可行的修复方案
方案一:通过ApplicationContext获取原型Bean
在Controller里注入Spring的上下文,每次需要ServiceImpl时从容器里拿新实例(原型作用域每次拿都是新的):
@RestController public class MyController { static int i = 0; private final ApplicationContext context; // 构造注入ApplicationContext public MyController(ApplicationContext context) { this.context = context; System.out.println("Inside Controller"); } @RequestMapping("/") public int post() { // 从容器获取Spring管理的ServiceImpl实例,此时Autowired会生效 ServiceImpl impl = context.getBean(ServiceImpl.class); return impl.name(i++); } }
方案二:用ObjectFactory优雅获取原型Bean
如果不想直接依赖ApplicationContext,可以用ObjectFactory来封装原型Bean的获取逻辑,更符合Spring的设计思想:
@RestController public class MyController { static int i = 0; private final ObjectFactory<ServiceImpl> serviceFactory; // 构造注入ObjectFactory public MyController(ObjectFactory<ServiceImpl> serviceFactory) { this.serviceFactory = serviceFactory; System.out.println("Inside Controller"); } @RequestMapping("/") public int post() { // 获取新的ServiceImpl实例,Spring会自动注入Customer ServiceImpl impl = serviceFactory.getObject(); return impl.name(i++); } }
额外提醒
- 原型作用域的Bean,只要是从Spring容器中获取的,Spring都会自动完成内部的
@Autowired注入,你不用手动处理。 - Controller请求方法的参数一般用来接收前端传的请求数据(比如JSON、表单字段),不要用来获取Spring容器里的业务Bean,这完全是两个不同的场景。
内容的提问来源于stack exchange,提问作者CPF
相关产品推荐
相关产品推荐

