Home > Net >  Does using @Import annotation create all beans defined in imported file?
Does using @Import annotation create all beans defined in imported file?

Time:11-16

A.java:

@Configuration
@Import(B.class)
class A {
   @Bean
   public X x(Y y) {
       return new X(y);
   }
}

B.java:

@Configuration
class B {
  @Bean
  public Y y() {
     return new Y();
  }
  // And some other beans are defined
}

Will all beans defined in B.java be instantiated when bean x is instantiated? Since the file B.java is imported by A.java.

CodePudding user response:

A Test:

A simple test to visualize your answer:

class ATest {
    private static final Logger LOGGER = LoggerFactory.getLogger(A.class);

    private ApplicationContext ctx;

    @BeforeEach
    void setUp() {
        ctx = new AnnotationConfigApplicationContext(A.class);
    }

    @Test
    void test() {
        for (String beanName: ctx.getBeanDefinitionNames()) {
            LOGGER.info("BEAN: "   beanName);
        }
    }
}

Output:

[main] INFO be.dog.d.steven.A - BEAN: org.springframework.context.annotation.internalConfigurationAnnotationProcessor
[main] INFO be.dog.d.steven.A - BEAN: org.springframework.context.annotation.internalAutowiredAnnotationProcessor
[main] INFO be.dog.d.steven.A - BEAN: org.springframework.context.event.internalEventListenerProcessor
[main] INFO be.dog.d.steven.A - BEAN: org.springframework.context.event.internalEventListenerFactory
[main] INFO be.dog.d.steven.A - BEAN: a
[main] INFO be.dog.d.steven.A - BEAN: org.company.B
[main] INFO be.dog.d.steven.A - BEAN: y
[main] INFO be.dog.d.steven.A - BEAN: x

As you can see, @Import did make the application context include all beans in class B as expected.

The first 4 beans are always created, even if you use just one empty class annotated with @Configuration to build the application context. The fifth bean that will always be created is the annotated class used to create the context.

In practice:

Although this works fine, it is cleaner to have your application do a @ComponentScan(basePackages = "org.company") in a certain package or folder. This way you do not always have to add new components to the @Import annotation. (You might also not want to scan the whole project when you are working on a bigger project, rather just folders containing actual components.)

You can however use @Import on test classes to only load an isolated part of the context for that test.

You can also set the logging level of the Spring Framework to DEBUG in the application.properties:

logging.level.org.springframework=DEBUG

This way you can also check the logs of your application to see what beans get created.

CodePudding user response:

First I ran the sample that is posted by you. Then I tested one sample with following variation,

@Configuration
@Import(B.class)
class A {
   @Bean
   public X x(Y y) {
       return new X(y);
   }
}

And then the last variation as following,

@Slf4j
@Configuration
class B {
    @Bean
    public Y y() {
        log.info("Creating bean Y in B {}", System.currentTimeMillis());
        return new Y();
    }

    @Bean
    public Z z(){
        log.info("Creating bean Z in B {}", System.currentTimeMillis());
        return new Z();
    }
    // And some other beans are defined
}

Here is what I inferred from my observations,

  • A bean is always when you're using the annotation @Bean, bean is declared from a class which is annotated with either @Component, @Configuration or @Service and your component class is part of your declared package in @ComponentScan, then Spring will always register your bean. I can safely say that @Import has very little to do with bean creation.
  • Upon running second first(one with default constructor) multiple times, I found bean X created before bean Y.
  • Upon running second variation where I declared more than one bean in class B, the order of bean creation was Y, X and then Z.

@Import is just used to group your bean definition source as I found here on Baeldung, @Import

  • Related