Spring MVC 4中Servlet的@Autowired依赖注入失败,如何实例化MyService?
我在基于Spring MVC的应用中实现了一个健康检查Servlet(HealthCheckController),尝试使用@Autowired注解注入MyService类,但该类无法被实例化。相关代码如下:
@WebServlet(name = "myServlet", urlPatterns = "/app2") public class HealthCheckController extends HealthCheckServlet{ /** The Constant serialVersionUID. */ private static final long serialVersionUID = 1L; @Autowired private MyService service; /** * method to check healthiness. * * @return true, if is healthy * @throws HealthCheckException the health check exception */ @Override public boolean isHealthy() throws HealthCheckException { try { service.showDetails("12", false,null); System.out.println("True"); return true; } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } return false; } }
想请教下如何正确为该Servlet提供MyService的依赖?
嘿,这个问题我之前碰到过,核心原因很明确:你的HealthCheckController是由Servlet容器(比如Tomcat)负责实例化的,不属于Spring容器管理的Bean,所以Spring的@Autowired注解根本没法生效,自然注入不了MyService。给你几个靠谱的解决办法:
方法一:手动从Spring上下文获取Bean
在Servlet的init方法里,通过Spring提供的工具类拿到WebApplicationContext,然后手动获取MyService的实例,就能正常使用了:
@Override public void init() throws ServletException { super.init(); // 获取Spring的Web上下文 WebApplicationContext context = WebApplicationContextUtils.getRequiredWebApplicationContext(getServletContext()); // 手动获取MyService实例 service = context.getBean(MyService.class); }
⚠️ 注意:要确保MyService类上标注了@Service或@Component注解,并且Spring的配置类(或者XML配置)已经开启了组件扫描,这样Spring才能把MyService纳入容器管理。
方法二:改成Spring MVC原生Controller(推荐)
既然是Spring MVC应用,完全没必要直接继承Servlet,直接改成Spring的Controller就好,这样整个类都由Spring管理,@Autowired就能正常工作了,还更符合Spring的架构设计:
@RestController @RequestMapping("/app2") public class HealthCheckController { @Autowired private MyService service; @GetMapping public ResponseEntity<String> checkHealth() { try { service.showDetails("12", false, null); return ResponseEntity.ok("Healthy"); } catch (Exception e) { e.printStackTrace(); return ResponseEntity.status(HttpStatus.SERVICE_UNAVAILABLE).body("Unhealthy"); } } }
这种方式不仅解决了依赖注入的问题,还能利用Spring MVC的各种特性,比如统一异常处理、请求参数解析等,非常推荐。
方法三:使用@Configurable(不推荐)
给HealthCheckController加上@Configurable注解,然后配置AspectJ编译时织入,让Spring接管Servlet的实例化。但这个配置比较复杂,需要额外引入AspectJ依赖,而且Servlet容器和Spring的生命周期容易出现冲突,一般不建议这么做。
最后再提醒下:不管用哪种方法,都要确保MyService已经被Spring正确扫描并实例化,不然就算拿到上下文也获取不到Bean哦~
内容的提问来源于stack exchange,提问作者MiniSu

