重复调用Destroy和New Context是不是很糟糕?

时间:2015-06-24 18:21:41

标签: java spring

假设我的主要课程是这样的:

public class TestTasker
{
    private static GenericXmlApplicationContext context; // to be accessed by static main

    public void runTask()
    {
        System.out.println("Current time is: " + new Date());

        context.destroy();
        initContext();

        // if I do this instead..
        // context.refresh();
        // I'd get an exception:
        // SEVERE: Invocation of method 'runTask' on target class [class spring.task.test.TestTasker] failed
        // java.lang.IllegalStateException: GenericApplicationContext does not support multiple refresh attempts: just call 'refresh' once

        // EDIT2: by using ClassPathXmlApplicationContext instead of generic context,
        // I can call context.refresh() with no error.
    }

    private static initContext()
    {
        context = new GenericXmlApplicationContext("AppContext.xml");
    }

    public static void main(String[] args)
    {
        initContext();
    }
}

AppContext.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" xmlns:task="http://www.springframework.org/schema/task"
    xmlns:util="http://www.springframework.org/schema/util" xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd
        http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.0.xsd">

    <!-- Task Scheduler -->
    <task:annotation-driven />
    <bean id="testTasker" class="spring.task.test.TestTasker" />
    <util:properties id="applicationProps" location="application.properties" />
    <context:property-placeholder
        properties-ref="applicationProps" />
    <task:scheduled-tasks>
        <task:scheduled ref="testTasker" method="runTask"
            cron="#{applicationProps['cron.expression']}" />
    </task:scheduled-tasks>

</beans>

application.properties

cron.expression=*/5 * * * * ?

如果我这样做,会有任何负面后果,例如内存泄漏(反复调用destroy和new context)吗?

有没有更好的解决方案?我只需要Spring自动/周期性地刷新 AppContext。

编辑:编辑了主类中的代码。调用context.refresh()会产生此异常,

SEVERE: Invocation of method 'runTask' on target class [class spring.task.test.TestTasker] failed java.lang.IllegalStateException: GenericApplicationContext does not support multiple refresh attempts: just call 'refresh' once

EDIT2 :通过使用ClassPathXmlApplicationContext代替通用上下文,我可以调用context.refresh(),但没有错误。

2 个答案:

答案 0 :(得分:1)

您可以使用context.refresh();

如果它失败了,它应该销毁已经创建的单例,以避免悬空资源。换句话说,在调用该方法之后,应该实例化全部或不实现单例。

答案 1 :(得分:0)

GenericXmlApplicationContext.refresh()的问题是,它不支持多次刷新。你可以请分享你的更新代码。看起来它在初始化后不止一次被调用。

这是春季文档的内容

与为每次刷新创建新的内部BeanFactory实例的其他ApplicationContext实现相比,此上下文的内部BeanFactory从一开始就可用,以便能够在其上注册bean定义。 AbstractApplicationContext.refresh()只能被调用一次。

对于XML bean定义的典型情况,只需使用ClassPathXmlApplicationContext或FileSystemXmlApplicationContext,它们更容易设置 - 但不太灵活,因为您可以只使用XML bean定义的标准资源位置,而不是混合任意bean定义格式。 Web环境中的等效项是XmlWebApplicationContext。

对于应该以可刷新的方式读取特殊bean定义格式的自定义应用程序上下文实现,请考虑从AbstractRefreshableApplicationContext基类派生。