I need help understanding how a spring boot application reads annotations in order to configure the application context. Let me give an example of what is confusing me: I have a spring boot application with a main class called ApplicationClass which has a main method and 3 configuration classes called FirstConfig, SecondConfig, and ThirdConfig. The main class component scans the FirstConfig configuration class, but not SecondConfig or ThirdConfig. FirstConfig imports SecondConfig but not ThirdConfig:
@SpringBootApplication(scanBasePackageClasses = {FirstConfig.class})
public class ApplicationClass {
public static void main(String[] args) {
...
SpringApplication.run(ApplicationClass.class, args);
}
}
@Configuration
@Import(value={SecondConfig.class})
public class FirstConfig { ... }
@Configuration
public class SecondConfig { ... }
@Configuration
public class ThirdConfig { ... }
When I run my application with gradle bootRun
and examine the application context, I find that, as expected, FirstConfig and SecondConfig were loaded into the application context because FirstConfig was included through component scanning and SecondConfig was included through the @Import annotation on FirstConfig, but ThirdConfig has not been loaded into the application context.
I then added lines of code to the ApplicationClass main method (before the call to SpringApplication.run) that used reflection to change the value of the @Import annotation on FirstConfig at runtime from value={SecondConfig.class} to instead be value={ThirdConfig.class}. I was also able to verify at runtime that the value of the annotation has indeed changed because the line of code FirstConfig.class.getAnnotation(Import.class).value()
returns {ThirdConfig.class} instead of {SecondConfig.class} (the method I used for modifying the value with reflection is spelled out in the top answer of this post. I assumed that spring boot configured the application context through reading annotations by using reflection; however this does not appear to be the case. Despite the fact that Import.value() was changed through reflection before the call to SpringApplication.run, when I check the application context, I find that it is still the case that FirstConfig and SecondConfig are loaded and ThirdConfig is not. I expected that if spring was using reflection to configure the application context, then after my reflection code runs in the main method FirstConfig and ThirdConfig would be in the application context but SecondConfig would not. Because this is not the case, it appears that spring does not use reflection to configure the application context based on annotations. If this is correct, then how does spring read annotations to configure the application context? Why did the application context contain {FirstConfig, SecondConfig} instead of {FirstConfig, ThirdConfig} as I expected.
P.S. I'm using the close to the latest versions of spring with JDK 17. Also, any alternate reflection-based solutions to achieving what I was trying to achieve would be appreciated.