当前位置: 首页 > 知识库问答 >
问题:

Dispatcher servlet上下文在spring上下文刷新后创建beanss,而不是使用“父”bean

陆臻
2023-03-14

当应用程序启动时,会引发两个上下文:一个用于org.springframework.web.context.WebApplicationContext事件,另一个用于org.springframework.web.context.WebApplicationContext:/派遣员事件,并且一切正常,派遣员上下文使用“父”bean而不是创建它自己的。当我使用ConfigurableApplication ationContext::刷新()(我使用rest api请求调用它)启动Spring上下文刷新时,只发送了一个ContextRenewEvent(第一个),当我尝试访问任何servlet组件(rest控制器)时,派遣员开始创建自己的bean,尽管刷新后创建了“主”bean。再次没有为派遣员上下文刷新发送事件。我需要使调度器上下文使用来自刷新的Web应用程序上下文的bean,而不是创建自己的。我认为问题是因为调度器上下文没有被主上下文刷新。也许它甚至不知道任何关于已提出的刷新上下文的事情。

web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
         version="3.1">

    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/application-*.xml</param-value>
    </context-param>

    <listener>
        <listener-class>com.app.web.CustomContextListener</listener-class>
    </listener>

    <listener>
        <listener-class>
            org.springframework.security.web.session.HttpSessionEventPublisher
        </listener-class>
    </listener>

    <servlet>
        <servlet-name>dispatcher</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>dispatcher</servlet-name>
        <url-pattern>/config.json</url-pattern>
    </servlet-mapping>

    <servlet-mapping>
        <servlet-name>default</servlet-name>
        <url-pattern>*.js</url-pattern>
    </servlet-mapping>
    <servlet-mapping>
        <servlet-name>default</servlet-name>
        <url-pattern>*.map</url-pattern>
    </servlet-mapping>
    <servlet-mapping>
        <servlet-name>default</servlet-name>
        <url-pattern>*.eot</url-pattern>
    </servlet-mapping>

    <servlet-mapping>
        <servlet-name>default</servlet-name>
        <url-pattern>*.css</url-pattern>
    </servlet-mapping>

    <servlet-mapping>
        <servlet-name>default</servlet-name>
        <url-pattern>*.woff</url-pattern>
    </servlet-mapping>

    <servlet-mapping>
        <servlet-name>default</servlet-name>
        <url-pattern>*.woff2</url-pattern>
    </servlet-mapping>

    <servlet-mapping>
        <servlet-name>default</servlet-name>
        <url-pattern>/assets/*</url-pattern>
    </servlet-mapping>

    <servlet-mapping>
        <servlet-name>default</servlet-name>
        <url-pattern>*.svg</url-pattern>
    </servlet-mapping>

    <servlet-mapping>
        <servlet-name>default</servlet-name>
        <url-pattern>*.ttf</url-pattern>
    </servlet-mapping>

    <servlet-mapping>
        <servlet-name>default</servlet-name>
        <url-pattern>*.ico</url-pattern>
    </servlet-mapping>

    <servlet-mapping>
        <servlet-name>default</servlet-name>
        <url-pattern>*.png</url-pattern>
    </servlet-mapping>

    <servlet-mapping>
        <servlet-name>default</servlet-name>
        <url-pattern>*.gif</url-pattern>
    </servlet-mapping>

    <servlet-mapping>
        <servlet-name>default</servlet-name>
        <url-pattern>*.jpg</url-pattern>
    </servlet-mapping>

    <servlet-mapping>
        <servlet-name>default</servlet-name>
        <url-pattern>*.jpeg</url-pattern>
    </servlet-mapping>

    <servlet-mapping>
        <servlet-name>default</servlet-name>
        <url-pattern>*.bmp</url-pattern>
    </servlet-mapping>

    <servlet-mapping>
        <servlet-name>default</servlet-name>
        <url-pattern>*.html</url-pattern>
    </servlet-mapping>

    <servlet-mapping>
        <servlet-name>dispatcher</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>

    <welcome-file-list>
        <welcome-file>index.html</welcome-file>
        <welcome-file>index.jsp</welcome-file>
    </welcome-file-list>

</web-app>

应用程序上下文. xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
    http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
    http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">

    <context:component-scan base-package="com.app"/>
    <import resource="classpath*:configuration-context.xml"/>

    <mvc:annotation-driven/>
    <aop:aspectj-autoproxy proxy-target-class="true"/>

    <bean class="com.ais.configuration.collection.CustomConfigLoader">
        <constructor-arg name="pathsHolder" ref="applicationPaths"/>
        <property name="location" value="app.properties"/>
        <property name="searchSystemEnvironment" value="true"/>
        <property name="ignoreResourceNotFound" value="false"/>
        <property name="ignoreUnresolvablePlaceholders" value="false"/>
    </bean>
</beans>

dispatcher-servlet.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
</beans>

共有1个答案

王杰
2023-03-14

对于其他任何寻找这个问题答案的人来说,这就是我解决问题的方式

我创建了实用程序类来存储应用程序中的所有应用程序上下文

public class ApplicationContextUtils
{
    public static final Set<ApplicationContext> AppContexts = new LinkedHashSet<>();
}

然后我编写了类来处理所有 ContextRefreshed 事件,并将相应的上下文放在实用程序类的 set 中

@Component
public class ContextRefreshedEventsHandler implements ApplicationListener<ContextRefreshedEvent>
{
    @Override
    public void onApplicationEvent( ContextRefreshedEvent event )
    {
        ApplicationContext app = event.getApplicationContext();
        ApplicationContextUtils.AppContexts.add( app );
    }
}

因此,当应用程序启动时,所有上下文都按其显示顺序存储在我的实用程序类中。在我的 RefreshService 中,我迭代了所有 contex 并刷新它们

List<ApplicationContext> appContexts = new ArrayList<>( ApplicationContextUtils.AppContexts );

        for( ApplicationContext applicationContext : appContexts )
            ( (ConfigurableApplicationContext)applicationContext ).refresh();

这解决了问题

 类似资料:
  • 我有一个使用子/父上下文关系的Spring应用程序。这样做的原因是为了确保子上下文从父上下文继承bean/资源,然后根据需要添加更多bean/资源来覆盖它们。但是,当子上下文关闭时(退出try/catch作用域),它开始对它引用的所有bean进行清理,包括父作用域中的bean。这是不可取的,因为我需要重用父上下文来创建另一个子上下文,但是现在它是垃圾,因为它包含了一堆已处理/关闭的bean。 问题

  • 我将Spring Boot与Spring集成在一起,我希望为每个<code>child() 此时此刻,我正在处理这个:(只有最相关的行) 我已经查看了SpringApplication ationBuilder方法,并且属性从父亲传播到孩子: 但是我需要动态加载一些属性,如下例所示: 从此示例中提取:Spring多个 imapAdapter 这是因为一些Spring集成组件将从配置文件中动态加载。

  • 同时,Puppy资源将更多地位于webMvc级别,并加载到DispatcherServlet的上下文中。 从我刚才读到的内容(现在我很有希望理解)来看,根上下文实际上是DispatcherServlet创建的上下文的‘父’上下文。这意味着根上下文中的bean实际上可以自动连接/注入到DispatcherServlet创建的上下文中的任何bean中。我只是了解了“嵌套”上下文的概念。这准确吗? 如果

  • 问题内容: 我已经使用和上下文init-parameter 配置了根应用程序上下文。 然后,JSF(* .jsf)变量解析器访问根上下文。它工作正常。 现在的问题是,经过的请求将获得另一个应用程序上下文,然后将单例bean实例化两次。 我不需要其他的应用程序上下文,如何指定它来重用由加载的现有根应用程序上下文? 注意 阅读答案中的参考页后,我知道根上下文和调度程序上下文之间存在上下文分隔,但是没有

  • 问题内容: 我有一个Spring bean(dao)对象,该对象通过以下xml在ServletContext中实例化: 该bean在我的webapp-servlet.xml文件中声明,并由我的应用程序在ServletContext中使用。 我也在使用SpringSecurity。据我了解,这在不同的上下文(SecurityContext)中运行。 我的应用程序具有webapp-security.x

  • opentelemetry javaagent all(版本0.17.0和1.0.1)是向Java应用程序添加跟踪信息的起点。自动仪表工作得很好。 我的一些应用程序无法自动检测。对于应用程序的这一部分,我首先使用span向代码中的有趣点添加注释。 现在,我已经达到了使用span注释进行简单注释的极限。然而,我的应用程序的底层框架允许我注册在特定点调用的回调,例如,我可以提供在客户端连接/断开连接时