There are several ways of defining Spring Beans in the Spring Framework. Each method has its own advantages and disadvantages. You may be wondering which one should you use. The answer is, it depends. The reality is in a large enterprise Spring project, you will likely encounter a combination of methods in defining Spring Beans. Neither is wrong, nor necessarily better. In legacy Spring applications, you’re likely to encounter XML based Spring Configuration. In new Spring applications, you’re likely to encounter more annotation based configurations and Java based configurations.
In this post, I’ll step you through common ways of defining Spring Beans. At the end of the post, I’ll show you how the different methods work seamlessly.
Say Hello Spring Bean
All the examples in this post will implement the following Interface. We will use simple Hello World type beans which will print a message to the system console.
1 package guru.springframework.hello; 2 3 /** 4 * Created by jt on 3/28/15. 5 */ 6 public interface HelloBean { 7 void sayHello(); 8 }
HelloBean
Spring Configuration
XML Based Configuration
XML based Spring Configuration has been around since the beginning of Spring. It is the oldest and most mature method of defining Spring Beans.
Hello Spring Bean
Here is the Spring Bean we will use for this example.
1 package guru.springframework.xml; 2 3 import guru.springframework.hello.HelloBean; 4 5 /** 6 * Created by jt on 3/28/15. 7 */ 8 public class XmlBean implements HelloBean { 9 @Override 10 public void sayHello() { 11 System.out.println("Hello, I‘m a XML Bean"); 12 } 13 }
XmlBean
Spring XML Configuration
1 <?xml version="1.0" encoding="UTF-8"?> 2 <beans xmlns="http://www.springframework.org/schema/beans" 3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 4 xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> 5 6 <bean id="xmlBean" class="guru.springframework.xml.XmlBean"/> 7 </beans>
Spring Xml Configuration
Application
The following code can be used to execute the example Spring Bean.
1 package guru.springframework.xml; 2 3 import org.springframework.boot.SpringApplication; 4 import org.springframework.boot.autoconfigure.SpringBootApplication; 5 import org.springframework.context.ApplicationContext; 6 import org.springframework.context.annotation.ImportResource; 7 8 /** 9 * Created by jt on 3/28/15. 10 */ 11 @SpringBootApplication 12 @ImportResource("classpath*:spring/spring-config.xml") 13 public class XmlApplication { 14 public static void main(String[] args) { 15 ApplicationContext ctx = SpringApplication.run(XmlApplication.class, args); 16 XmlBean bean = (XmlBean) ctx.getBean("xmlBean"); 17 bean.sayHello(); 18 } 19 }
XmlApplication
Output
1 . ____ _ __ _ _ 2 /\\ / ___‘_ __ _ _(_)_ __ __ _ \ \ \ 3 ( ( )\___ | ‘_ | ‘_| | ‘_ \/ _` | \ \ \ 4 \\/ ___)| |_)| | | | | || (_| | ) ) ) ) 5 ‘ |____| .__|_| |_|_| |_\__, | / / / / 6 =========|_|==============|___/=/_/_/_/ 7 :: Spring Boot :: (v1.2.2.RELEASE) 8 9 2015-03-28 10:38:02.260 INFO 66700 --- [ main] guru.springframework.xml.XmlApplication : Starting XmlApplication on Johns-MacBook-Pro.local with PID 66700 (/Users/jt/src/springframework.guru/blog/springbeans/target/classes started by jt in /Users/jt/src/springframework.guru/blog/springbeans) 10 2015-03-28 10:38:02.319 INFO 66700 --- [ main] s.c.a.AnnotationConfigApplicationContext : Refreshing org.spring[email protected]3e57cd70: startup date [Sat Mar 28 10:38:02 EDT 2015]; root of context hierarchy 11 2015-03-28 10:38:03.229 INFO 66700 --- [ main] o.s.b.f.xml.XmlBeanDefinitionReader : Loading XML bean definitions from URL [file:/Users/jt/src/springframework.guru/blog/springbeans/target/classes/spring/spring-config.xml] 12 2015-03-28 10:38:03.656 INFO 66700 --- [ main] o.s.j.e.a.AnnotationMBeanExporter : Registering beans for JMX exposure on startup 13 2015-03-28 10:38:03.669 INFO 66700 --- [ main] guru.springframework.xml.XmlApplication : Started XmlApplication in 1.813 seconds (JVM running for 2.311) 14 Hello, I‘m a XML Bean 15 2015-03-28 10:38:03.670 INFO 66700 --- [ Thread-1] s.c.a.AnnotationConfigApplicationContext : Closing org.spring[email protected]3e57cd70: startup date [Sat Mar 28 10:38:02 EDT 2015]; root of context hierarchy 16 2015-03-28 10:38:03.671 INFO 66700 --- [ Thread-1] o.s.j.e.a.AnnotationMBeanExporter : Unregistering JMX-exposed beans on shutdown
Output
Java Based Configuration
In Spring 3, Java based configuration was released. The Spring community is gradually converting over to prefer the use of Java based configuration over XML based configuration. It is somewhat easier to use than XML. Since the configuration is in Java, you do have a tremendous amount of flexibility in defining beans. You’re no longer bound by the constraints of describing beans in XML, and have the full power of the Java language at your disposal.
Hello Spring Bean
1 package guru.springframework.javaconfig; 2 3 import guru.springframework.hello.HelloBean; 4 5 /** 6 * Created by jt on 3/28/15. 7 */ 8 public class JavaConfigBean implements HelloBean { 9 @Override 10 public void sayHello() { 11 System.out.println("Hello, I‘m a Java Config bean"); 12 } 13 }
JavaConfigBean
Java Configuration Class
The following class is a Spring Configuration class. The annotation @Configuration at the top of the class defines the class as a configuration class. The class will be picked up in a Spring component scan. It can also be imported into other configuration classes too. Objects returned @Bean annotation will be registered as Spring Beans. By convention the name of the registered Spring Bean will be set equal to the name of the method.
1 package guru.springframework.javaconfig; 2 3 import org.springframework.context.annotation.Bean; 4 import org.springframework.context.annotation.Configuration; 5 6 /** 7 * Created by jt on 3/28/15. 8 */ 9 @Configuration 10 public class JavaConfig { 11 @Bean 12 public JavaConfigBean javaConfigBean(){ 13 return new JavaConfigBean(); 14 } 15 }
JavaConfig
Application
The following code can be used to execute the example Spring Bean.
1 package guru.springframework.javaconfig; 2 3 import org.springframework.boot.SpringApplication; 4 import org.springframework.boot.autoconfigure.SpringBootApplication; 5 import org.springframework.context.ApplicationContext; 6 import org.springframework.context.annotation.Import; 7 8 /** 9 * Created by jt on 3/28/15. 10 */ 11 @SpringBootApplication 12 @Import(JavaConfig.class) 13 public class JavaConfigApplication { 14 public static void main(String[] args) { 15 ApplicationContext ctx = SpringApplication.run(JavaConfigApplication.class, args); 16 JavaConfigBean bean = (JavaConfigBean) ctx.getBean("javaConfigBean"); 17 bean.sayHello(); 18 } 19 }
JavaConfigApplication
Output
1 . ____ _ __ _ _ 2 /\\ / ___‘_ __ _ _(_)_ __ __ _ \ \ \ 3 ( ( )\___ | ‘_ | ‘_| | ‘_ \/ _` | \ \ \ 4 \\/ ___)| |_)| | | | | || (_| | ) ) ) ) 5 ‘ |____| .__|_| |_|_| |_\__, | / / / / 6 =========|_|==============|___/=/_/_/_/ 7 :: Spring Boot :: (v1.2.2.RELEASE) 8 9 2015-03-28 11:13:46.387 INFO 66847 --- [ main] g.s.javaconfig.JavaConfigApplication : Starting JavaConfigApplication on Johns-MacBook-Pro.local with PID 66847 (/Users/jt/src/springframework.guru/blog/springbeans/target/classes started by jt in /Users/jt/src/springframework.guru/blog/springbeans) 10 2015-03-28 11:13:46.447 INFO 66847 --- [ main] s.c.a.AnnotationConfigApplicationContext : Refreshing org.spring[email protected]3e57cd70: startup date [Sat Mar 28 11:13:46 EDT 2015]; root of context hierarchy 11 2015-03-28 11:13:47.579 INFO 66847 --- [ main] o.s.j.e.a.AnnotationMBeanExporter : Registering beans for JMX exposure on startup 12 2015-03-28 11:13:47.607 INFO 66847 --- [ main] g.s.javaconfig.JavaConfigApplication : Started JavaConfigApplication in 1.651 seconds (JVM running for 2.265) 13 Hello, I‘m a Java Config bean 14 2015-03-28 11:13:47.609 INFO 66847 --- [ Thread-1] s.c.a.AnnotationConfigApplicationContext : Closing org.spring[email protected]3e57cd70: startup date [Sat Mar 28 11:13:46 EDT 2015]; root of context hierarchy 15 2015-03-28 11:13:47.610 INFO 66847 --- [ Thread-1] o.s.j.e.a.AnnotationMBeanExporter : Unregistering JMX-exposed beans on shutdown
Output
Annotation Based Configuration
Spring also can detect beans based on class level annotations. Any class annotated with with @Component ,@Service , @Controller , or @Repository will be considered a Spring Bean. The class must reside in a package which had been identified for a component scan. Spring will scan the package for annotated classes. Any class detected will be managed by the Spring Context at run time.
Hello Spring Bean
1 package guru.springframework.componentscan; 2 3 import guru.springframework.hello.HelloBean; 4 import org.springframework.stereotype.Component; 5 6 /** 7 * Created by jt on 3/28/15. 8 */ 9 @Component 10 public class ComponentScanBean implements HelloBean { 11 public void sayHello(){ 12 System.out.println("Hello, I‘m a Component Scan Bean"); 13 } 14 }
ComponentScanBean
Application
The following code can be used to execute the example Spring Bean.
1 package guru.springframework.componentscan; 2 3 import org.springframework.boot.SpringApplication; 4 import org.springframework.boot.autoconfigure.SpringBootApplication; 5 import org.springframework.context.ApplicationContext; 6 7 /** 8 * Created by jt on 3/28/15. 9 */ 10 @SpringBootApplication 11 public class ComponentScanApplication { 12 public static void main(String[] args) { 13 ApplicationContext ctx = SpringApplication.run(ComponentScanApplication.class, args); 14 ComponentScanBean bean = (ComponentScanBean) ctx.getBean("componentScanBean"); 15 bean.sayHello(); 16 } 17 }
ComponentScanApplication
Output
1 . ____ _ __ _ _ 2 /\\ / ___‘_ __ _ _(_)_ __ __ _ \ \ \ 3 ( ( )\___ | ‘_ | ‘_| | ‘_ \/ _` | \ \ \ 4 \\/ ___)| |_)| | | | | || (_| | ) ) ) ) 5 ‘ |____| .__|_| |_|_| |_\__, | / / / / 6 =========|_|==============|___/=/_/_/_/ 7 :: Spring Boot :: (v1.2.2.RELEASE) 8 9 2015-03-28 15:21:17.576 INFO 67246 --- [ main] g.s.c.ComponentScanApplication : Starting ComponentScanApplication on Johns-MacBook-Pro.local with PID 67246 (/Users/jt/src/springframework.guru/blog/springbeans/target/classes started by jt in /Users/jt/src/springframework.guru/blog/springbeans) 10 2015-03-28 15:21:17.632 INFO 67246 --- [ main] s.c.a.AnnotationConfigApplicationContext : Refreshing org.spring[email protected]3e57cd70: startup date [Sat Mar 28 15:21:17 EDT 2015]; root of context hierarchy 11 2015-03-28 15:21:18.850 INFO 67246 --- [ main] o.s.j.e.a.AnnotationMBeanExporter : Registering beans for JMX exposure on startup 12 2015-03-28 15:21:18.867 INFO 67246 --- [ main] g.s.c.ComponentScanApplication : Started ComponentScanApplication in 1.671 seconds (JVM running for 2.218) 13 Hello, I‘m a Component Scan Bean 14 2015-03-28 15:21:18.869 INFO 67246 --- [ Thread-1] s.c.a.AnnotationConfigApplicationContext : Closing org.spring[email protected]3e57cd70: startup date [Sat Mar 28 15:21:17 EDT 2015]; root of context hierarchy 15 2015-03-28 15:21:18.870 INFO 67246 --- [ Thread-1] o.s.j.e.a.AnnotationMBeanExporter : Unregistering JMX-exposed beans on shutdown
Output
Using Spring Bean Configurations Together
While there are different ways of defining Spring Beans, its important to remember the different methods can be used together. Its very common to use multiple methods of defining Spring Beans in a single application.
Spring Bean Application
We can use the beans previously defined to demonstrate how this works seamlessly. The Spring component scan functionality will detect classes annotated as Spring Beans, and classes marked as configuration classes which also define Spring Beans. In the following code example, the annotation@ComponentScan("guru.springframework") tells Spring to perform a component scan on the package guru.springframework.
This technique will work for annotated classes, but it not pick up XML configuration files. The annotation@ImportResource("classpath*:spring/spring-config.xml") will bring the specified xml file into the Spring context.
The class below is annotated to perform the component scan, which will pick up Spring Beans defined in Java configuration classes, Spring Beans defined with annotations, and Spring Beans defined in XML configuration files.
1 package springbeans; 2 3 import guru.springframework.componentscan.ComponentScanBean; 4 import guru.springframework.hello.HelloBean; 5 import guru.springframework.javaconfig.JavaConfigBean; 6 import guru.springframework.xml.XmlBean; 7 import org.springframework.boot.SpringApplication; 8 import org.springframework.boot.autoconfigure.SpringBootApplication; 9 import org.springframework.context.ApplicationContext; 10 import org.springframework.context.annotation.ComponentScan; 11 import org.springframework.context.annotation.ImportResource; 12 13 import java.util.ArrayList; 14 import java.util.List; 15 16 @SpringBootApplication 17 @ComponentScan("guru.springframework") 18 @ImportResource("classpath*:spring/spring-config.xml") 19 public class SpringBeansApplication { 20 21 public static void main(String[] args) { 22 ApplicationContext ctx = SpringApplication.run(SpringBeansApplication.class, args); 23 24 List<HelloBean> helloBeans = new ArrayList<HelloBean>(); 25 helloBeans.add((ComponentScanBean) ctx.getBean("componentScanBean")); 26 helloBeans.add((JavaConfigBean) ctx.getBean("javaConfigBean")); 27 helloBeans.add((XmlBean) ctx.getBean("xmlBean")); 28 29 for(HelloBean helloBean : helloBeans){ 30 helloBean.sayHello(); 31 } 32 } 33 }
SpringBeansApplication
Output
When you run the above class, you will see the following output.
1 . ____ _ __ _ _ 2 /\\ / ___‘_ __ _ _(_)_ __ __ _ \ \ \ 3 ( ( )\___ | ‘_ | ‘_| | ‘_ \/ _` | \ \ \ 4 \\/ ___)| |_)| | | | | || (_| | ) ) ) ) 5 ‘ |____| .__|_| |_|_| |_\__, | / / / / 6 =========|_|==============|___/=/_/_/_/ 7 :: Spring Boot :: (v1.2.2.RELEASE) 8 9 2015-03-28 15:47:11.531 INFO 67265 --- [ main] springbeans.SpringBeansApplication : Starting SpringBeansApplication on Johns-MacBook-Pro.local with PID 67265 (/Users/jt/src/springframework.guru/blog/springbeans/target/classes started by jt in /Users/jt/src/springframework.guru/blog/springbeans) 10 2015-03-28 15:47:11.602 INFO 67265 --- [ main] s.c.a.AnnotationConfigApplicationContext : Refreshing org.spring[email protected]3e57cd70: startup date [Sat Mar 28 15:47:11 EDT 2015]; root of context hierarchy 11 2015-03-28 15:47:12.544 INFO 67265 --- [ main] o.s.b.f.xml.XmlBeanDefinitionReader : Loading XML bean definitions from URL [file:/Users/jt/src/springframework.guru/blog/springbeans/target/classes/spring/spring-config.xml] 12 2015-03-28 15:47:12.725 INFO 67265 --- [ main] o.s.b.f.xml.XmlBeanDefinitionReader : Loading XML bean definitions from URL [file:/Users/jt/src/springframework.guru/blog/springbeans/target/classes/spring/spring-config.xml] 13 2015-03-28 15:47:12.753 INFO 67265 --- [ main] o.s.b.f.s.DefaultListableBeanFactory : Overriding bean definition for bean ‘xmlBean‘: replacing [Generic bean: class [guru.springframework.xml.XmlBean]; scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null; defined in URL [file:/Users/jt/src/springframework.guru/blog/springbeans/target/classes/spring/spring-config.xml]] with [Generic bean: class [guru.springframework.xml.XmlBean]; scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null; defined in URL [file:/Users/jt/src/springframework.guru/blog/springbeans/target/classes/spring/spring-config.xml]] 14 2015-03-28 15:47:13.014 INFO 67265 --- [ main] o.s.j.e.a.AnnotationMBeanExporter : Registering beans for JMX exposure on startup 15 2015-03-28 15:47:13.028 INFO 67265 --- [ main] springbeans.SpringBeansApplication : Started SpringBeansApplication in 1.878 seconds (JVM running for 2.474) 16 Hello, I‘m a Component Scan Bean 17 Hello, I‘m a Java Config bean 18 Hello, I‘m a XML Bean 19 2015-03-28 15:47:13.029 INFO 67265 --- [ Thread-1] s.c.a.AnnotationConfigApplicationContext : Closing org.spring[email protected]3e57cd70: startup date [Sat Mar 28 15:47:11 EDT 2015]; root of context hierarchy 20 2015-03-28 15:47:13.030 INFO 67265 --- [ Thread-1] o.s.j.e.a.AnnotationMBeanExporter : Unregistering JMX-exposed beans on shutdown
Output