如何让 WebApplicationContext 访问 ApplicationContext 中的 bean?
How can I make WebApplicationContext access beans in ApplicationContext?
这就是我在 Java Web 应用程序中尝试 bootstrap Spring 的方式:
public class SpringBootstrap implements WebApplicationInitializer {
public void onStartup(ServletContext servletContext) throws ServletException {
final AnnotationConfigApplicationContext rootContext = new AnnotationConfigApplicationContext();
rootContext.register(RootContextConfiguration.class);
final AnnotationConfigWebApplicationContext webContext = new AnnotationConfigWebApplicationContext();
webContext.register(WebContextConfiguration.class);
webContext.setParent(rootContext);
final DispatcherServlet dispatcherServlet = new DispatcherServlet(webContext);
final ServletRegistration.Dynamic dispatcher = servletContext.addServlet("springDispatcher", dispatcherServlet);
dispatcher.setLoadOnStartup(1);
dispatcher.addMapping("/");
final ContextLoaderListener contextLoadListener = new ContextLoaderListener(webContext);
servletContext.addListener(contextLoadListener);
}
}
而RootContextConfiguration和WebContextConfiguration类如下:
@Configuration
@ComponentScan(basePackages = "biz.tugay.janeleven.root")
public class RootContextConfiguration {
}
@Configuration
@EnableWebMvc
@ComponentScan(basePackages = "biz.tugay.janeleven.web")
public class WebContextConfiguration {
@Bean
public ViewResolver viewResolver() {
InternalResourceViewResolver resolver = new InternalResourceViewResolver();
return resolver;
}
}
当我尝试将应用程序部署到 Tomcat 并开始时,我将得到:
Caused by:
org.springframework.beans.factory.NoSuchBeanDefinitionException: No
qualifying bean of type
[biz.tugay.janeleven.root.service.AppUserService] found for
dependency: expected at least 1 bean which qualifies as autowire
candidate for this dependency. Dependency annotations:
{@org.springframework.beans.factory.annotation.Autowired(required=true)}
我在这里还包含了 HelloServlet 和 AppUserService 类,以及它们的包信息:
包 biz.tugay.janeleven.root.service;
@Service
public class AppUserService {
public AppUser addAppUser(String name) {
final AppUser appUser = new AppUser(name);
AppUserDB.addUser(appUser);
return appUser;
}
public Collection<AppUser> getAllAppUsers() {
return AppUserDB.getAll();
}
}
package biz.tugay.janeleven.web;
@Controller
@RequestMapping(value = "/")
public class HelloWorldServlet {
@Autowired
private AppUserService appUserService;
@RequestMapping(value = "", method = RequestMethod.GET)
public String helloWorld(Model model) {
final Collection<AppUser> appUserList = appUserService.getAllAppUsers();
model.addAttribute("appUserList", appUserList);
return "hello.jsp";
}
@RequestMapping(value = "", method = RequestMethod.POST)
public String addApplicationUser(@RequestParam("username") String username) {
appUserService.addAppUser(username);
return "redirect:/";
}
}
我的期望是,WebContextConfiguration 应该能够找到由 RootContextConfiguration 管理的 bean,因为我正在调用:
webContext.setParent(rootContext);
在 bootstrap 过程中。但显然我错过了一些东西。
您说得对,Web 上下文将从根上下文继承,但是
初始化 servletContext.addListener() 时没有包含 rootContext;请参阅下面的类似代码,这将帮助您解决问题。
@Override
public void onStartup(ServletContext servletContext) throws ServletException {
AnnotationConfigWebApplicationContext rootContext = new AnnotationConfigWebApplicationContext();
rootContext.register(AppConfig.class);
servletContext.addListener(new ContextLoaderListener(rootContext));
AnnotationConfigWebApplicationContext dispatcherContext = new AnnotationConfigWebApplicationContext();
dispatcherContext.register(WebConfig.class);
ServletRegistration.Dynamic dispatcher = servletContext.addServlet("dispatcher",
new DispatcherServlet(dispatcherContext));
dispatcher.setLoadOnStartup(1);
dispatcher.addMapping("/");
}
这就是我在 Java Web 应用程序中尝试 bootstrap Spring 的方式:
public class SpringBootstrap implements WebApplicationInitializer {
public void onStartup(ServletContext servletContext) throws ServletException {
final AnnotationConfigApplicationContext rootContext = new AnnotationConfigApplicationContext();
rootContext.register(RootContextConfiguration.class);
final AnnotationConfigWebApplicationContext webContext = new AnnotationConfigWebApplicationContext();
webContext.register(WebContextConfiguration.class);
webContext.setParent(rootContext);
final DispatcherServlet dispatcherServlet = new DispatcherServlet(webContext);
final ServletRegistration.Dynamic dispatcher = servletContext.addServlet("springDispatcher", dispatcherServlet);
dispatcher.setLoadOnStartup(1);
dispatcher.addMapping("/");
final ContextLoaderListener contextLoadListener = new ContextLoaderListener(webContext);
servletContext.addListener(contextLoadListener);
}
}
而RootContextConfiguration和WebContextConfiguration类如下:
@Configuration
@ComponentScan(basePackages = "biz.tugay.janeleven.root")
public class RootContextConfiguration {
}
@Configuration
@EnableWebMvc
@ComponentScan(basePackages = "biz.tugay.janeleven.web")
public class WebContextConfiguration {
@Bean
public ViewResolver viewResolver() {
InternalResourceViewResolver resolver = new InternalResourceViewResolver();
return resolver;
}
}
当我尝试将应用程序部署到 Tomcat 并开始时,我将得到:
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [biz.tugay.janeleven.root.service.AppUserService] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
我在这里还包含了 HelloServlet 和 AppUserService 类,以及它们的包信息:
包 biz.tugay.janeleven.root.service;
@Service
public class AppUserService {
public AppUser addAppUser(String name) {
final AppUser appUser = new AppUser(name);
AppUserDB.addUser(appUser);
return appUser;
}
public Collection<AppUser> getAllAppUsers() {
return AppUserDB.getAll();
}
}
package biz.tugay.janeleven.web;
@Controller
@RequestMapping(value = "/")
public class HelloWorldServlet {
@Autowired
private AppUserService appUserService;
@RequestMapping(value = "", method = RequestMethod.GET)
public String helloWorld(Model model) {
final Collection<AppUser> appUserList = appUserService.getAllAppUsers();
model.addAttribute("appUserList", appUserList);
return "hello.jsp";
}
@RequestMapping(value = "", method = RequestMethod.POST)
public String addApplicationUser(@RequestParam("username") String username) {
appUserService.addAppUser(username);
return "redirect:/";
}
}
我的期望是,WebContextConfiguration 应该能够找到由 RootContextConfiguration 管理的 bean,因为我正在调用:
webContext.setParent(rootContext);
在 bootstrap 过程中。但显然我错过了一些东西。
您说得对,Web 上下文将从根上下文继承,但是 初始化 servletContext.addListener() 时没有包含 rootContext;请参阅下面的类似代码,这将帮助您解决问题。
@Override
public void onStartup(ServletContext servletContext) throws ServletException {
AnnotationConfigWebApplicationContext rootContext = new AnnotationConfigWebApplicationContext();
rootContext.register(AppConfig.class);
servletContext.addListener(new ContextLoaderListener(rootContext));
AnnotationConfigWebApplicationContext dispatcherContext = new AnnotationConfigWebApplicationContext();
dispatcherContext.register(WebConfig.class);
ServletRegistration.Dynamic dispatcher = servletContext.addServlet("dispatcher",
new DispatcherServlet(dispatcherContext));
dispatcher.setLoadOnStartup(1);
dispatcher.addMapping("/");
}