Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring Boot AutoConfiguration Order

Tags:

spring-boot

I am having some trouble getting some Spring configuration to be applied in the desired order with Spring Boot in a multi-module Maven project.

I have modules A and B that are written by me and a dependency on a third party module that I have no control over in module C (dependencies are as follows: A depends on C, B depends on A)

In module A I have a class annotated with @Configuration and also @AutoConfigureBefore(ClassFromModuleD.class). In module B I have another class annotated with @Configuration and also @AutoConfigureBefore(ClassFromModuleA.class)

I was hoping that this would result in the bean definitions in my module B being configured first, followed by beans in my module A configuration class then finally the ones in C.

I also tried adding a META-INF/spring.factories file to both module A and B which declares the single configuration file present in its own module. E.g. for module A

org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.exmaple.moduleAConfiguration

and in module B:

org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.exmaple.moduleBConfiguration

I am not seeing the desired order of configuration, in fact, it seems to be the exact opposite to what I want. I have used logging statements and a debugger to step through and it seems the config from Module C is applied first, followed by A then finally B.

Could anyone point out what I may have missed or if there is another way to do this? thanks very much in advance.

like image 354
David Avatar asked Dec 27 '14 13:12

David


People also ask

How does autoconfiguration work in spring boot?

Spring Boot auto-configuration attempts to automatically configure your Spring application based on the jar dependencies that you have added. For example, If HSQLDB is on your classpath, and you have not manually configured any database connection beans, then we will auto-configure an in-memory database.

What is @configuration @EnableAutoConfiguration and @ComponentScan?

How They Differ. The main difference between these annotations is that @ComponentScan scans for Spring components while @EnableAutoConfiguration is used for auto-configuring beans present in the classpath in Spring Boot applications.

What is the difference between @configuration and autoconfiguration?

You can use @EnableAutoConfiguration annotation along with @Configuration annotation. It has two optional elements, exclude : if you want to exclude the auto-configuration of a class. excludeName : if you want to exclude the auto-configuration of a class using fully qualified name of class.


1 Answers

Spring AutoConfiguration is used to provide a basic configuration if certain classes are in the classpath or not.

This is used e.g. to provide a basic Jpa configuration if Hibernate is on the classpath.

If you want to configure the order in which beans are instantiated by spring you can use

@DependsOn("A") 
public class B{
...    
}

This would create bean "A", than "B".

However, the order you desire may not be possible. You wrote :

A depends on C, B depends on A

If 'depends on' means : A needs C to be instantiated, the beans must be created in the following order :

  1. C - because C depends on nothing
  2. A - because A depends on C, which is already created.
  3. B - because B depends on A, which is already created.

Spring automatically detects the dependencies by analyzing the bean classes.

If A has an autowired property or a constructor argument of type C, spring 'knows' that it must instantiate C before A.

In most cases this works quite well.

In some cases spring cannot 'guess' the dependencies and creates beans in an unwanted order. Than you can 'inform' spring through the @DependsOn annotation about the dependency. Spring will try to change the order accordingly.

In your case, if the dependencies you described are not visible for spring, and the dependencies are not needed to create the beans, you can try to change the order with @DependsOn :

A depends on C, B depends on A

Could be achieved with

@DependsOn("C") 
public class A{
   ...    
}

@DependsOn("A") 
public class B{
   ...    
}

// C comes from another module
// and no need to annotate
like image 142
Stefan Isele - prefabware.com Avatar answered Oct 22 '22 05:10

Stefan Isele - prefabware.com