【问题标题】:Spring can't see beans between servlet-context and contextConfigLocation beansSpring 看不到 servlet-context 和 contextConfigLocation bean 之间的 bean
【发布时间】:2012-03-20 20:18:11
【问题描述】:

我有一个这样设置的 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>
</servlet>

<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,它会出现它找不到它。这些是作为两个不同的上下文创建的吗?为什么会发生这种情况/通常会这样工作?

【问题讨论】:

    标签: java spring spring-mvc jakarta-ee spring-bean


    【解决方案1】:

    Spring容器肯定可以看到组件扫描context的base包决定的组件,你可以从context中获取bean。

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

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

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

    @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 还没有初始化,所以我们可以说 bean 在 rootContext 初始化时不可见)

    但是你可以在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, beanNameHandlerMapping, @98654336@, @987654336 ,resourceHandlerMapping,mvcResourceUrlProvider,defaultServletHandlerMapping,requestMappingHandlerAdapter,mvcConversionService,mvcValidator,mvcUriComponentsContributor,httpRequestHandlerAdapter,httpRequestHandlerAdapter,simpleControllerHandlerAdapter,mvcViewResolver,mvcViewResolver,mvcViewResolver,mvcViewResolver p>

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

    @Configuration
    @ComponentScan(basePackages = { "com.your.configuration.package", "org.springframework.web.servlet" })
    public class RootConfiguration
    

    如果您希望注入的依赖项在您的 rootContext 中可用并且可以在您的 servlet-filter 中访问,上述配置将很有帮助。例如,如果您在过滤器中捕获异常并希望发送与HttpMessageConverter 发送的响应相同但在 servletContext 中配置的错误响应,那么您可能希望访问该配置的转换器以发送相同的响应。
    请注意,下面的自动装配在 servlet-filters 中不起作用

    @Autowired
    private ApplicationContext appContext;
    

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

    所以,要在过滤器中获取 applicationContext

    public class YourFilter implements Filter
    {
        private ApplicationContext appContext;
    
        @Override
        public void init(FilterConfig filterConfig) throws ServletException
        {
            Filter.super.init(filterConfig);
            appContext = WebApplicationContextUtils.getRequiredWebApplicationContext(filterConfig.getServletContext());
        }
    }
    

    希望它能清楚地说明如何在上下文之间访问 bean。

    【讨论】:

      【解决方案2】:

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

      DispatcherServlet (servlet-context.xml) 中的 bean 可以访问 ContextLoaderListener (configuration-context.xml) 中的 bean,但反之则不行。

      所以把基本的东西放在configuration-context.xml 和网络相关的一次到servlet-context.xml

      @另请参阅此 Stack Overflow 问题:ContextLoaderListener or not?

      【讨论】:

      • 你能告诉我为什么我不能从我的 web servlet 访问 applicationContext 中定义的 txManager 吗?
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-04-10
      • 2015-09-17
      • 1970-01-01
      • 2013-11-11
      • 1970-01-01
      • 2011-10-11
      相关资源
      最近更新 更多