Spring Nested @Configuration Classes
June 07, 2019
Spring @Configuration
is annotated at class level to indicate that a class declares one or more @Bean
methods. @Configuration
classes can be nested within one another. We need to register only outer configuration class against application context and this will bootstrap nested configuration classes as well. Using nested configuration classes we can avoid @Import
annotation. Here on this page, we will provide example of creating nested configurations and bootstrapping them against application context.
Contents
Create Nested Configuration Class
Here in our example we have two configuration classes nested within one another.OuterConfig.java
package com.concretepage; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; @Configuration @ComponentScan("com.concretepage") public class OuterConfig { @Bean public OuterTask getOuterTask() { return new OuterTask("Outer Task"); } @Configuration public static class InnerConfig { @Bean public InnerTask getInnerTask() { return new InnerTask("Inner Task"); } } }
package com.concretepage; public class InnerTask { private String name; public InnerTask(String name) { this.name = name; } public String getName() { return name; } }
package com.concretepage; public class OuterTask { private String name; public OuterTask(String name) { this.name = name; } public String getName() { return name; } }
Register Outer Configuration Class
When we register outer configuration class against application context, it will bootstrap outer and inner configuration classes as well.MySpringApp.java
package com.concretepage; import org.springframework.context.annotation.AnnotationConfigApplicationContext; public class MySpringApp { public static void main(String[] args) { AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(OuterConfig.class); OuterTask outerTask = ctx.getBean(OuterTask.class); System.out.println(outerTask.getName());// will work InnerTask innerTask = ctx.getBean(InnerTask.class); System.out.println(innerTask.getName()); // will work ctx.registerShutdownHook(); ctx.close(); } }
Outer Task Inner Task
OuterConfig.java
package com.concretepage; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; @Configuration @ComponentScan("com.concretepage") public class OuterConfig { @Autowired private InnerTask innerTask; @Bean public OuterTask getOuterTask() { System.out.println(innerTask.getName()); return new OuterTask("Outer Task"); } @Configuration public static class InnerConfig { @Bean public InnerTask getInnerTask() { return new InnerTask("Inner Task"); } } }
Register Inner Configuration Class
When we register inner configuration class against application context, it will bootstrap inner configuration class only and not outer configuration class within which it is nested.MySpringApp.java
package com.concretepage; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import com.concretepage.OuterConfig.InnerConfig; public class MySpringApp { public static void main(String[] args) { AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(InnerConfig.class); InnerTask innerTask = ctx.getBean(InnerTask.class); System.out.println(innerTask.getName()); //will work OuterTask outerTask = ctx.getBean(OuterTask.class); System.out.println(outerTask.getName()); //will throw exception ctx.registerShutdownHook(); ctx.close(); } }
References
Spring Doc: @ConfigurationSpring @Configuration Annotation