Based on the following pseudo-code

Spring does NOT auto-start a solo Lifecycle bean:

  @Component public class ManualService implements Lifecycle {} 

Spring auto-starts any Lifecycle bean that is dependent of a SmartLifecycle:

  @Component public class ManualService implements Lifecycle {} 
  @Component public class AutoService implements SmartLifecycle {
    @Autowired private ManualService dependent;
    public boolean isAutoStartup() { return true; }
  }

Here is where I got confused. Spring auto-starts a Lifecycle bean even though, a few lines later, it determines it is not required:

@SpringBootApplication
public class Issue31337 {
  public static void main(String[] args) { SpringApplication.run(Issue31337.class, args); }

  @Component public static class ManualService implements Lifecycle {
    private boolean running;
    public void start() { running = true; System.out.println(this.getClass().getSimpleName()); }
    public void stop() { running = false; }
    public boolean isRunning() { return running; }
  }
  @Component public static class AutoService extends ManualService implements SmartLifecycle {
    @Autowired private ManualService dependent;
    public boolean isAutoStartup() { return false; }
  }
}

This means the mere presence of the SmartLifecycle bean in the context triggers all of stuff to occur. This is made all the harder to follow by #15122 which describes how a transitive Lifecycle bean is not started.

Now the behaviour is arguable both ways but surely autoStartup=false says "Leave me alone, I've got this". In my case, the AutoService start() explicitly calls dependent.start() so my workaround is to stop using Lifecycle to represent anything manually startable.


Affects: spring-context 5.3.28

Comment From: snicoll

@drekbour I didn't get what's confusing. The Javadoc of Lifecycle and SmartLifecycle clearly explains the difference between the two.

Note that the present Lifecycle interface is only supported on top-level singleton beans. On any other component, the Lifecycle interface will remain undetected and hence ignored. Also, note that the extended SmartLifecycle interface provides sophisticated integration with the application context's startup and shutdown phases.

but surely autoStartup=false says "Leave me alone, I've got this

If you call startyourself, I have no idea what you're expecting. It should start the component, the autoStartup bit is about doing this for you.

I am willing to give it another try, but not based on pseudo code. If you believe something is still wrong after having reviewed the javadoc of both classes, please share a small sample that reproduces only the confusing case you've tried to describe. You can do that by attaching a zip to this issue or pushing the code to another GitHub repository.

Comment From: drekbour

If you call start yourself, I have no idea what you're expecting

Nor should you - I got this.

the autoStartup bit is about doing this for you.

But autoStartup is false so AutoService is not started by Spring but before it checks autoStartup and decides to skip it, DefaultLifecycleProcessor has already called start() on all of its Lifecycle dependencies. They did not need to be started.

not based on pseudo code

I have no IDE available (if such a thing can be true once onto the internet!) so edited the example freehand into something that should compile.

Comment From: snicoll

Cool. But we need a sample we can run ourselves. Not text in code that we’ll have to copy and miss a step you didn’t provide.

Comment From: spring-projects-issues

If you would like us to look at this issue, please provide the requested information. If the information is not provided within the next 7 days this issue will be closed.

Comment From: spring-projects-issues

Closing due to lack of requested feedback. If you would like us to look at this issue, please provide the requested information and we will re-open the issue.