Spring无法在servlet-context和contextConfigLocation bean之间看到bean

时间:2012-03-02 10:09:45

标签: java spring spring-mvc

我有一个像这样设置的spring mvc项目:

<servlet>
<servlet-name>appServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
  <param-name>contextConfigLocation</param-name>
  <param-value>/WEB-INF/spring-contexts/servlet-context.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>

<context-param>
  <param-name>contextConfigLocation</param-name>
  <param-value>/WEB-INF/spring-contexts/configuration-context.xml</param-value>
</context-param>

如果我在configuration-context.xml中创建一个bean并在servlet-context.xml中引用一个bean,它就无法找到它。这些是作为两个不同的背景创建的吗?为什么这种情况会发生/一般都这样?

2 个答案:

答案 0 :(得分:6)

是的,有两个上下文相互堆叠(父和子上下文)。

DispatcherServlet(servlet-context.xml)中的bean可以从ContextLoaderListener(configuration-context.xml)访问bean,但不是相反。

因此,将configuration-context.xml和网络相关的基本内容放入servlet-context.xml

@参见Stack Overflow问题:ContextLoaderListener or not?

答案 1 :(得分:0)

Spring容器肯定可以查看由上下文的组件扫描基础包决定的组件,并且您可以从上下文中获取Bean。

spring中有两种类型的上下文
1.根上下文(ApplicationContext)
2. Servlet上下文(WebApplicationContext)

在rootContext中定义的bean对servletContext的可见性-是

默认情况下,在根上下文中定义的Bean在所有servlet上下文中始终可见。例如,可以在servlet上下文中访问在根上下文中定义的dataSource bean,如下所示。

@Configuration
public class RootConfiguration
{
    @Bean
    public DataSource dataSource()
    {
       ...
    }
}

@Configuration
@EnableWebMvc
@ComponentScan(basePackages = "com.pvn.mvctiles")
public class ServletConfiguration implements WebMvcConfigurer
{
    @Autowired
    private DataSource dataSource;

    ...
}

servletContext中定义的bean对rootContext的可见性-是*

(为什么*是)
1.上下文顺序的初始化首先是rootContext,然后是ServletContext。 在根上下文配置类/ xml中,如果尝试获取在ServletContext中定义的bean,则将获得NULL。 (因为servletContext尚未初始化,因此我们可以说在rootContext初始化时不可见bean)

但是您可以在初始化ServletContext后获得在ServletContext中定义的bean(您可以通过应用程序上下文获取bean)

您可以通过以下方式打印并确认

applicationContext.getBeanDefinitionNames();


2.如果要在过滤器或另一个servlet上下文中访问servlet上下文的bean,请将"org.springframework.web.servlet"基本包添加到根配置类/ xml

@Configuration
@ComponentScan(basePackages = "org.springframework.web.servlet" )
public class RootConfiguration

添加后,您可以从应用程序上下文中获取所有下面的bean

springSecurityConfigtilesConfigurerthemeSourcethemeResolvermessageSourcelocaleResolverrequestMappingHandlerMappingmvcPathMatchermvcUrlPathHelpermvcContentNegotiationManagerviewControllerHandlerMappingbeanNameHandlerMappingresourceHandlerMappingmvcResourceUrlProviderdefaultServletHandlerMappingrequestMappingHandlerAdapter,{ {1}},mvcConversionServicemvcValidatormvcUriComponentsContributorhttpRequestHandlerAdaptersimpleControllerHandlerAdapterhandlerExceptionResolvermvcViewResolver

如果要从rootContext获取自定义bean,请按如下所示将基本包值添加到rootContext组件扫描。

mvcHandlerMappingIntrospector

如果希望注入的依赖项在rootContext中可用并且可以在servlet过滤器中进行访问,则上述给定的配置将非常有用。例如,如果您在过滤器中捕获异常并想要发送与@Configuration @ComponentScan(basePackages = { "com.your.configuration.package", "org.springframework.web.servlet" }) public class RootConfiguration 发送的响应相同但在ServletContext中配置的错误响应,则您可能希望访问该已配置的转换器以发送相同的响应。 />
请注意,下面的自动装配不适用于servlet过滤器

HttpMessageConverter

这在servlet过滤器中不起作用,因为过滤器是在初始化spring容器之前初始化的。(取决于过滤器和DelegatingProxyFilter的顺序)

因此,要在过滤器中获取applicationContext

@Autowired
private ApplicationContext appContext;

希望它为如何在上下文之间访问bean提供了清晰的思路。