Spring Boot中XML配置下@Autowired注入Repository为空问题求助
问题说明
在Spring Boot项目中,使用@Autowired注入继承CrudRepository的StudentRepo接口时,仅在通过spring.xml配置从控制器获取SignupService类实例的场景下,注入的studentRepo引用为空。由于XML配置要求Bean为类,无法直接为StudentRepo接口创建Bean,但已添加<jpa:repositories>标签扫描Repository包,问题仍存在。若不使用XML配置,仅在SignupService上添加@Component注解并在控制器中@Autowired注入SignupService,项目可正常运行,需解决@Autowired与XML配置的兼容问题。
报错信息
Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is java.lang.NullPointerException] with root cause java.lang.NullPointerException: null at com.myspringproject1.service.SignupService.doSignup(SignupService.java:81) ~[classes/:na] at com.myspringproject1.controller.TestController.doSignup(TestController.java:42) ~[classes/:na] at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_202] at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_202] at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_202] at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_202]
相关代码与配置
spring.xml配置
<beans ..... > <context:annotation-config/> <bean id="signupServiceBean" class="com.myspringproject1.service.SignupService"></bean> <!-- <bean id="StudentRepoBean" class="com.myspringproject1.repo.StudentRepo"></bean> --> <!-- 注释掉的Repo接口Bean配置 --> <jpa:repositories base-package="com.myspringproject1.repo"/> </beans>
Controller代码
@Controller public class TestController { @RequestMapping(method = RequestMethod.POST, value = "signup") public ModelAndView doSignup(HttpServletRequest request) { BeanFactory factory = new XmlBeanFactory(new ClassPathResource("spring.xml")); SignupService signupService = (SignupService) factory.getBean("signupServiceBean"); ModelAndView mv = new ModelAndView(); boolean result = signupService.doSignup(request); if (result == true) { User newUser = (User) request.getSession().getAttribute("user"); mv.setViewName("signup_result"); mv.addObject("newUser", newUser); return mv; } else { mv.setViewName("signup_result"); mv.addObject("newUser", null); return mv; } } }
Repository接口
@Repository public interface StudentRepo extends CrudRepository<User, Integer>{ }
Service类
@Service public class SignupService { @Autowired private StudentRepo studentRepo; public boolean doSignup(HttpServletRequest request) { // 业务逻辑... User result = studentRepo.save(user); // 此处因studentRepo为空触发NullPointerException // 后续逻辑... } }
解决方案
1. 避免手动创建新的Spring容器
你在控制器中通过new XmlBeanFactory()创建了一个全新的Spring容器,这个容器和Spring Boot启动时初始化的主容器完全独立。主容器中会通过<jpa:repositories>生成StudentRepo的代理Bean,但新容器无法访问主容器的Bean,导致SignupService中的studentRepo无法被注入。
正确的做法是直接在控制器中@Autowired注入SignupService,无需手动从XML获取:
@Controller public class TestController { @Autowired private SignupService signupService; @RequestMapping(method = RequestMethod.POST, value = "signup") public ModelAndView doSignup(HttpServletRequest request) { ModelAndView mv = new ModelAndView(); boolean result = signupService.doSignup(request); if (result) { User newUser = (User) request.getSession().getAttribute("user"); mv.setViewName("signup_result"); mv.addObject("newUser", newUser); return mv; } mv.setViewName("signup_result"); mv.addObject("newUser", null); return mv; } }
2. 将XML配置整合到Spring Boot主容器
如果必须保留XML配置,需要将spring.xml导入到Spring Boot的主容器中,而不是手动创建新容器。在Spring Boot启动类上添加@ImportResource注解:
@SpringBootApplication @ImportResource("classpath:spring.xml") public class YourApplication { public static void main(String[] args) { SpringApplication.run(YourApplication.class, args); } }
这样XML中定义的signupServiceBean和<jpa:repositories>生成的Repository代理Bean都会被加载到主容器中,@Autowired可以正常注入依赖。
3. 确认Repository扫描配置生效
<jpa:repositories base-package="com.myspringproject1.repo"/>标签会自动扫描指定包下的Repository接口,并为其生成代理实现类作为Spring Bean,无需手动为接口配置Bean。确保base-package的值正确指向你的Repository所在包,主容器就能扫描到这些Bean并完成注入。
内容的提问来源于stack exchange,提问作者Zeeshan

