Spring 管理的 Bean 可直接使用 @Autowired,但 Servlet 與 Filter 由 Servlet 容器實例化,不在 Spring 容器中,無法直接注入。
public class MyServlet extends HttpServlet {
@Autowired private UserService userService; // 無效!
@Override
public void init(ServletConfig config) throws ServletException {
ServletContext ctx = config.getServletContext();
WebApplicationContext wac = WebApplicationContextUtils.getWebApplicationContext(ctx);
AutowireCapableBeanFactory factory = wac.getAutowireCapableBeanFactory();
factory.autowireBean(this); // 或 factory.configureBean(this, "beanName");
}
}
缺點:硬編碼 Bean 名稱、侵入式程式碼、非標準 DI 風格。
public class DelegatingServletProxy extends GenericServlet {
private String targetBean;
private Servlet proxy;
@Override
public void init() throws ServletException {
this.targetBean = getServletName(); // 從 web.xml 取得
getServletBean();
proxy.init(getServletConfig());
}
private void getServletBean() {
WebApplicationContext wac = WebApplicationContextUtils
.getRequiredWebApplicationContext(getServletContext());
this.proxy = (Servlet) wac.getBean(targetBean);
}
@Override
public void service(ServletRequest req, ServletResponse res)
throws ServletException, IOException {
proxy.service(req, res); // 委派給真正的 Servlet
}
}
@Component("userServlet") // Bean 名稱對應 web.xml servlet-name
public class UserServlet extends HttpServlet {
@Autowired private UserManager userManager; // 正常注入
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
// 業務邏輯
}
}
<servlet>
<servlet-name>userServlet</servlet-name> <!-- 必須與 @Component 值一致 -->
<servlet-class>com.example.DelegatingServletProxy</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>userServlet</servlet-name>
<url-pattern>/userServlet</url-pattern>
</servlet-mapping>
請求 → DelegatingServletProxy (容器管理)
→ Spring 容器查找 "userServlet" Bean
→ UserServlet (Spring 管理,已注入依賴)
→ 執行業務邏輯
Spring 內建 DelegatingFilterProxy,配置方式類似:
<filter>
<filter-name>securityFilter</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
對應的 Spring Bean 需實作 javax.servlet.Filter 介面。
@SpringBootApplication
public class Application {
@Bean
public ServletRegistrationBean<UserServlet> userServlet() {
return new ServletRegistrationBean<>(new UserServlet(), "/userServlet");
}
}
Spring Boot 自動將 Servlet 註冊為 Bean 並掛載,無需 web.xml、無需代理類別。