【问题标题】:I can't seem to get an implementation of Spring's Lifecycle working我似乎无法实现 Spring 的生命周期工作
【发布时间】:2011-06-06 22:32:12
【问题描述】:

我需要在 Spring 的应用程序上下文加载后立即发生一些事情。据我了解,我需要创建 Lifecycle 的实现并将 bean 引用放入上下文中。所以我在我的上下文中有这样的东西:

<bean id="mySpringLifecycle" class="com.my.project.MySpringLifecycle" />

这个类看起来像这样:

public class MySpringLifecycle implements Lifecycle {

    @Override
    public void start() {
        System.out.println("The lifecycle has started.");
    }

    @Override
    public void stop() {
        return;
    }

    @Override
    public boolean isRunning() {
        return true;
    }
}

我没有收到任何错误,但 MySpringLifecycle 从未打印出“生命周期已开始。”,我的应用程序启动得很好。

编辑:

这是固定代码:

public class MySpringLifecycle implements SmartLifecycle {

    private volatile boolean isRunning = false;

    @Override
    public boolean isAutoStartup() {
        return true;
    }

    @Override
    public void stop(Runnable r) {
        System.out.println("STOPPED RUNNABLE!!!");
        isRunning = false;
    }

    @Override
    public void start() {
        System.out.println("STARTED!!!");
        isRunning = true;
    }

    @Override
    public void stop() {
        System.out.println("STOPPED!!!");
        isRunning = false;
    }

    @Override
    public boolean isRunning() {
        return isRunning;
    }

    @Override
    public int getPhase() {
        return 1;
    }
}

作为旁注,我还想提一下我也可以使用的替代解决方案。我的 web.xml 中有以下内容:

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

<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

ContextLoaderListener 上有一个名为 contextInitialized 的方法。所以我所做的是创建自己的实现并将其添加到 web.xml 中。在我的实现中,我扩展了 ContextLoaderListener,为 contextInitialized 方法提供了一个覆盖,首先为该方法调用 super,然后执行我自己的功能。这只会执行一次,并且似乎运行良好。

【问题讨论】:

  • 引用自static.springsource.org/spring/docs/3.0.x/reference/… 可以看到SmartLifecycle 定义的stop 方法接受回调。任何实现都必须在该实现的关闭过程完成后调用该回调的 run() 方法。
  • 如果你的类另外扩展了另一个类怎么办。此外,提到的类在 spring 中定义。如何在您的类示例中实例化这些参数?

标签: spring spring-mvc


【解决方案1】:

两种方法:

  1. 实现 SmartLifecycle 而不是 Lifecycle 并确保从 isAutoStartup() 返回 true

  2. 实现ApplicationListener&lt;ContextRefreshedEvent&gt;。在这种情况下,只有一种方法可以实现,而不是 SmartLifecycle 的 6 种方法。

【讨论】:

  • 不幸的是,ContextRefreshedEvent 在启动过程中会被多次调用,而不仅仅是一次。我尝试了 ContextStartedEvent,但它不会在应用程序启动时触发,因为默认生命周期似乎没有调用 start()。
  • 当我实现 SmartLifecycle 时,唯一被调用的是公共 void stop(Runnable r) 覆盖。显然,我缺少一些实现细节来完成这项工作。
  • 确保isRunning() 返回false,直到调用start()stop() 不会被调用,除非 isRunning() 返回 true。
  • Re: ContextRefreshedEvent 被多次调用,见stackoverflow.com/questions/6164573/…
  • 似乎没有人能准确解释为什么 start() 方法在实现生命周期时没有被调用。这是一个错误吗?
【解决方案2】:

如果您修改 MySpringLifecycle 以实现 SmartLifecycle 而不是 Lifecycle,则您的 sn-p 中的 System.outs 将按照您的预期打印。

【讨论】:

    【解决方案3】:

    我不确定,但您 might 需要一个 LifecycleProcessor 以及一个或多个 Lifecycle 对象。

    【讨论】:

    • 否 - DefaultLifecyleProcessor 会自动添加到上下文中。
    【解决方案4】:

    根据您所说的“在 Spring 的应用程序上下文加载后立即”的含义,InitializingBean 的实现可能就是您正在寻找的。 LifeCycle 可能太低级了。

    【讨论】:

    • InitializingBean#afterPropertiesSet() 在上下文完全构造之前被调用,所以如果你依赖另一个 bean,就会发生不好的事情。
    猜你喜欢
    • 1970-01-01
    • 2019-11-27
    • 1970-01-01
    • 1970-01-01
    • 2020-05-02
    • 2019-12-18
    • 1970-01-01
    • 2014-12-04
    • 1970-01-01
    相关资源
    最近更新 更多