用Spring容器管理Bean是我们一惯的做法,这里的Spring容器指的就是Spring上下文。一般来说,我们会使用注入的方式将所需要的Bean注入到目标Target,但有时还是会存在不适合注入的情况,例如动态获取之类的,这时我们可能会直接去Spring上下文中去取。笔者就经常使用ContextLoader.getCurrentWebApplicationContext().getBean("")的方式去获取Bean。
前两天笔者在项目中引入了hibernate-validate库,在Spring-MVC.xml配置文件中增加了hibernate-validate的相关配置,为了不影响之前固有接口,笔者准备使用编程式验证,将Spring-MVC中得validator注入到所有controller的共同父类中去。可是发现,竟然从Spring上下文中取不出validator来。
查了下资料,发现原来是有两个上下文,Spring上下文保存在ServetContext中,追查源码可以看到key是
String ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE = WebApplicationContext.class.getName() + ".ROOT";
所以除了上面那种方式,我们还可以通过WebApplicationContextUtils.getWebApplicationContext(ServletContext);WebApplicationContextUtils.getWebApplicationContext(request.getSession().getServletContext())这两种方式,其实是一种方式,只是使用的位置不同而已,最开始用的方式在任何地方都可以使用,更加通用。
Spring-MVC上下文被称为子上下文,集成于Spring上下文,相应地Spring上下文被称为父上下文。我们都知道,子可以访问父,父不能访问子,所以出现了前面的错误,当然,如果最开始就把validator配置在Spring上下文中就不会有这个问题。Spring-MVC上下文也保存在ServletContext中,每产生一个Request,将会把Spring-MVC上下文保存在Request中,对应的key是
public static final String WEB_APPLICATION_CONTEXT_ATTRIBUTE = DispatcherServlet.class.getName() + ".CONTEXT";
所以我们可以通过RequestContextUtils.getWebApplicationContext(request)来获取Spring-MVC上下文。