title: How does Lifecycle interface work in Spring? What are "top-level singleton beans"?
body: <p>It is said in Spring javadoc, that "Note that the Lifecycle interface is only supported on top-level singleton beans." Here <a href="http://static.springsource.org/spring/docs/3.1.0.M1/javadoc-api/org/springframework/context/Lifecycle.html" rel="noreferrer">URL</a></p>
  
  <p>My <code>LifecycleBeanTest.xml</code> describes bean as follows:</p>
  
  <pre><code>&lt;beans ...&gt;
      &lt;bean id="lifecycle" class="tests.LifecycleBean"/&gt;
  &lt;/beans&gt;
  </code></pre>
  
  <p>so it looks "topish" and "singletonish" enough.</p>
  
  <p>What does it mean? How to make Spring know about my bean implementing <code>Lifecycle</code> and do something with it?</p>
  
  <p>Suppose my main method looks following in Spring</p>
  
  <pre><code>public static void main(String[] args) {
      new ClassPathXmlApplicationContext("/tests/LifecycleBeanTest.xml").close();
  }
  </code></pre>
  
  <p>so, it instantiates context and then closes it immediately.</p>
  
  <p>May I create some bean in my configuration, which delays <code>close()</code> execution until application do all it's works? So that main method thread wait for application termination?</p>
  
  <p>For example, the following bean does not work in way I thought. Neither <code>start()</code> not <code>stop()</code> is called.</p>
  
  <pre><code>package tests;
  
  import org.slf4j.Logger;
  import org.slf4j.LoggerFactory;
  import org.springframework.context.Lifecycle;
  
  public class LifecycleBean implements Lifecycle {
  
      private static final Logger log = LoggerFactory.getLogger(LifecycleBean.class);
  
      private final Thread thread = new Thread("Lifecycle") {
          {
              setDaemon(false);
              setUncaughtExceptionHandler(new UncaughtExceptionHandler() {
  
                  @Override
                  public void uncaughtException(Thread t, Throwable e) {
                      log.error("Abnormal thread termination", e);
                  }
              });
          }
  
          public void run() {
              for(int i=0; i&lt;10 &amp;&amp; !isInterrupted(); ++i) {
                  log.info("Hearbeat {}", i);
                  try {
                      sleep(1000);
                  } catch (InterruptedException e) {
                      return;
                  }
              }
          };
      };
  
  
      @Override
      public void start() {
          log.info("Starting bean");
          thread.start();
      }
  
      @Override
      public void stop() {
          log.info("Stopping bean");
          thread.interrupt();
          try {
              thread.join();
          } catch (InterruptedException e) {
              Thread.currentThread().interrupt();
              return;
          }
      }
  
      @Override
      public boolean isRunning() {
          return thread.isAlive();
      }
  
  }
  </code></pre>
  
  <p><strong>UPDATE 1</strong></p>
  
  <p>I know I can wait for bean in code. It is interesting to hook into Spring itself.</p>