我有一个像这样设置的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,它就无法找到它。这些是作为两个不同的背景创建的吗?为什么这种情况会发生/一般都这样?
答案 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)
默认情况下,在根上下文中定义的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;
...
}
(为什么*是)
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
springSecurityConfig
,tilesConfigurer
,themeSource
,themeResolver
,messageSource
,localeResolver
,requestMappingHandlerMapping
,mvcPathMatcher
,mvcUrlPathHelper
,mvcContentNegotiationManager
,viewControllerHandlerMapping
,beanNameHandlerMapping
,resourceHandlerMapping
,mvcResourceUrlProvider
,defaultServletHandlerMapping
,requestMappingHandlerAdapter
,{ {1}},mvcConversionService
,mvcValidator
,mvcUriComponentsContributor
,httpRequestHandlerAdapter
,simpleControllerHandlerAdapter
,handlerExceptionResolver
,mvcViewResolver
如果要从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提供了清晰的思路。