7

I have a Spring Boot application with the following structure

com.package
   Application - annotated with @SpringBootApplication
   Configuration - annotated with @Configuration
   Component1 - annotated with @Component, constructor annotated with @Autowired
com.package.subpackage
   Component2 - annotated with @Component, constructor annotated with @Autowired

My application class is

package com.package;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

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

When I start the application both Component1 and Component2 are identified as candidate components. However, only Component1 is instantiated.

Component2 will only instantiate when I make either of the following changes

  1. I move it to com.package i.e. the same as Component1
  2. I declare it as a @Autowired field in com.package.Configuration

Why does Spring Boot discover the component but not instantiate it in this case? Are there differences in how @ComponentScan works with regards to discovering vs instantiating @Component?

Mark
  • 28,783
  • 8
  • 63
  • 92
  • I removed my answer because I did not get the package structure. Can your bean be lazily instantiated @Lazy or lazy-init=true? That would match the described behaviour – Grzegorz Piwowarek Aug 17 '17 at 11:18
  • How are you testing that it isn't instantiated? Each component should be created regardless if it is used or not. Please add your `Application` class. – M. Deinum Aug 17 '17 at 11:22
  • I'm testing by logging in the constructor and @PostConstruct method. @Lazy(value = false) does not make a difference. – Mark Aug 17 '17 at 11:28
  • 1
    It would be helpful if you posted components and configuration class file too. – loyalBrown Aug 17 '17 at 12:52
  • I seriously didn't find anything wrong in this code, 'coz it looks fine to me by project structure as well as annotation **@Component**. – Mehraj Malik Aug 17 '17 at 13:46
  • @xenteros why is PostConstruct risky for components? – Mark Aug 17 '17 at 14:24
  • @Mark because you don't have any guarantee that anything would be injected so far – xenteros Aug 17 '17 at 14:26
  • @xenteros even when everything is autowired via constructor? – Mark Aug 17 '17 at 14:27
  • @Mark I believe so, but I base on personal experience with a problem I once solved by removing post construct. Maybe you should ask Baeldung? – xenteros Aug 17 '17 at 14:32
  • 1
    Thanks everyone for the help. Turns out Component1 was blocking the main thread stopping Component2 from being initialised. – Mark Aug 17 '17 at 14:55

1 Answers1

1

In my case it was not an issue with Spring Boot itself.

The @PostConstruct method for Component1 was blocking the main thread hence Component2 was not initialised.

Using @Autowired or moving to the same package obviously triggered the @PostConstruct method of Component2 before Component1.

Mark
  • 28,783
  • 8
  • 63
  • 92