Spring bean management using Java configuration

Learn to manage Spring beans using Java configuration

Spring beans are configured using the traditional XML approach. In this article, you will learn to write Spring beans and configure them using pure Java based configuration instead of using XML. The article will cover various annotations you can use to configure the bean. It will illustrate the Java based configuration by comparing it with the traditional XML based approach.

Rajeev Hathi, Java Architect, Writer

Rajeev Hathi works as a Software Consultant for the J2EE platform. His professional interests are architecting, designing and developing J2EE-based applications.  He has attained SUN certifications in Java and J2EE technologies (Core Java, Web, EJB, Architect). He has contributed several technical papers for IBM developerWorks portal. He is also the co-author of the book Apache CXF Web Service Development. His pastime hobbies are listening to music and watching sports. The author's official web site is http://www.rajeevhathi.com which is a technical blog site and he can be reached at rajeevhathi@gmail.com.



19 July 2011

Also available in Chinese Russian Japanese

Overview

Spring framework as we all know is a driver of the Inversion of Control (IOC) or Dependency Injection (DI) pattern, and it does so through its container based configuration. Traditionally, Spring allows the developer to manage bean dependencies using XML based configuration through the use of application context XML file. This file is external to the application and it holds definition of beans and its dependencies for that application. While it is easy and convenient to use the XML configuration, there is also an alternative way through which one can define bean and its dependencies. Its called as Java based configuration. Unlike XML, Java based configuration enables you to manage beans programatically. This can be acheived through use of various annotations. The article will illustrate Java configuration example by comparing it with traditional XML configuration approach. This will help developer understand the concepts better. The article will illustrate the basic use of Java based confiuration in following steps:

  • Understanding @Configuration and @Bean annotations
  • Registering config class with AnnotationConfigApplicationContext
  • Configuring Web application
  • Implementing bean lifecycle callbacks and scope

We will take the 'Create Course' use case of an Online University. As part of course creation process, you also create topics or modules and each topic may have different assignments. So we create three beans viz. Course, Module and Assignment. The Course bean will have a reference to Module bean which in turn wlll hold reference to Assignment bean.

Understanding @Configuration and @Bean annotations

In an ideal scenario, you would define the beans in an XML that represents the application context. The following code shows the context XML with bean definitions from the create course use case:

Listing 1. XML with bean definitions
<beans>
	<bean id="course" class="demo.Course">
		<property name="module" ref="module"/>
  	</bean>
	
	<bean id="module" class="demo.Module">
		<property name="assignment" ref="assignment"/>
  	</bean>
	
	<bean id="assignment" class="demo.Assignment" />
</beans>

The above XML is what you typically write to configure beans with Spring. The XML defines Course bean that has reference to Module bean. The Module bean has a reference to Assignment bean. You will now make rid of this XML and instead write a Java code equivalent. You will define the above specified beans using Java based configuration. We will replace the XML with the Java class that will now act as a platform for bean configuration. Let's name the class as AppContext.java. The following code shows AppContext class.

Listing 2. AppContext configuration class that contains bean definitions
@Configuration
public class AppContext {
	@Bean
	public Course course() {
		Course course = new Course();
		course.setModule(module());
		return course;
	}

	@Bean
	public Module module() {
		Module module = new Module();
		module.setAssignment(assignment());
		return module;
	}

	@Bean
	public Assignment assignment() {
		return new Assignment();
	}
}

As you see from the above code, the beans are now defined programatically as part of Java based configuration. The AppContext class now represents configuration class just like the XML. It is acheived through the use of @Configuration annotation. The @Configuration annotation is placed above the class. It tells the Spring container that this is a configuration class having bean definitions and dependencies. The @Bean annotation is used to define the bean. The said annotation is placed above the method that instantiates the bean and sets the dependency. The method name is the same as bean id or name by default. The return type of the method is the bean that is registered to Spring application context. You use setter methods of the bean to set the dependencies and the container will invoke them to wire the associations. Java based configuration can also be looked as annotation based configuration

Registering config class with AnnotationConfigApplicationContext

In the traditional XML approach, you would use ClassPathXmlApplicationContext class to load the external XML context file. But with Java based configuration, there is AnnotationConfigApplicationContext class. AnnotationConfigApplicationContext class is one such implementation of ApplicationContext interface that enables you to register annotated configuration classes. The configuration class here is AppContext declared using @Configuration annotation. Once you register the said class, all bean types returned by the @Bean annotated methods also gets registered. The below code illustrates the use of AnnotationConfigApplicationContext class:

Listing 3. Registering AppContext class with AnnotationConfigApplicationContext
public static void main(String[] args) {
  ApplicationContext ctx = new AnnotationConfigApplicationContext(AppContext.class);
  Course course = ctx.getBean(Course.class);
  course.getName();
}

As seen from the above code, the AppContext configuration class is registered by passing it to the AnnotationConfigApplicationContext constructor. Alternatively you can also use the register method of the said context class to register the configuration class. The below code shows the alternatively way.

Listing 4. Registering AppContext class: alternative way
public static void main(String[] args) {
  ApplicationContext ctx = new AnnotationConfigApplicationContext();
  ctx.register(AppContext.class)
}

Registering configuration class automatically registers @Bean annotated method names and therefore its corresponding beans viz Course, Module and Assignment. You can then use the getBean method to get the relavant bean and invoke its business methods. So as you see, its so simple to write the Java based configuration class and register it with Spring context. The next section will discuss using Java based configuration with web application.

Configuring Web application

Traditionally, you would configure Spring Web applications through the use of XmlWebApplicationContext context by specifying the path to external XML context file in the web deployment descriptor file web.xml. The XMLWebApplicationContext is the default context class used by web application. The following code depicts element in web.xml pointing to external XML context file that will be loaded by ContextLoaderListener listener class.

Listing 5. web.xml using external XML context file
<web-app>
	<context-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>/WEB-INF/applicationContext.xml</param-value>
	</context-param>
	<listener>
		<listener-class>
			org.springframework.web.context.ContextLoaderListener
		</listener-class>
	</listener>
	<servlet>
	<servlet-name>sampleServlet</servlet-name>
	<servlet-class>
		org.springframework.web.servlet.DispatcherServlet
	</servlet-class>
	</servlet>

...
</web-app>

You will now change the above code in web.xml to use AnnotationConfigApplicationContext class. Remember, XmlWebApplicationContext is the default context implementation used by Spring for web applications and therefore you never specify this context class explicitly in your web.xml file. Now as you will be using Java based configuration, you will need to specify AnnotationConfigApplicationContext class in your web.xml file while configuring it for web application. The above code is revised to look like this:

Listing 6. Revised web.xml that uses AnnotationConfigApplicationContext
<web-app>
	<context-param>
		<param-name>contextClass</param-name>
		<param-value>
			org.springframework.web.context.
			support.AnnotationConfigWebApplicationContext
		</param-value>
	</context-param>
	<context-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>
			demo.AppContext
		</param-value>
	</context-param>
	<listener>
		<listener-class>
			org.springframework.web.context.ContextLoaderListener
		</listener-class>
	</listener>
	<servlet>
	<servlet-name>sampleServlet</servlet-name>
	<servlet-class>
		org.springframework.web.servlet.DispatcherServlet
	</servlet-class>
	<init-param>
		<param-name>contextClass</param-name>
		<param-value>
			org.springframework.web.context.
			support.AnnotationConfigWebApplicationContext
		</param-value>
	</init-param>
	</servlet>

...
</web-app>

The above revised web.xml now defines AnnotationConfigWebApplicationContext context class as part of context parameter and servlet elements. The context configuration location now points to the AppContext configuration class. That was simple. The next section will illustrate implementing lifecycle callbacks and scope of the bean.

Implementing bean lifecycle callbacks and scope

Lifecycle callbacks

You can also manage lifecycle of beans using Java based configuration. The @Bean supports two attributes viz. initMethod and destroyMethod that can be used to define the lifecycle methods. The lifecycle methods are called by container when the bean is instantiated or about to be destroyed. The lifecycle methods are also called callback methods as it will be called by the container. The bean registered with @Bean annotation also supports the standard @PostConstruct and @PreDestroy annotations as part of JSR-250. If you are using XML approach to define the beans then you would use the bean element to define the lifecycle callback methods. The below code shows how you would normally define the callbacks using bean element in the XML configuration.

Listing 7. Using XML approach for lifecycle callbacks
<bean id="course" class="demo.Course" init-method="setup" destroy-method="cleanup" >
	<property name="module" ref="module"/>
</bean>

The following code illustrates the use of lifecycle methods with Java configuration

Listing 8. Implementing bean lifecycle methods using AppContext config class
@Configuration
public class AppContext {
	@Bean(initMethod = "setup", destroyMethod = "cleanup")
	public Course course() {
		Course course = new Course();
		course.setModule(module());
		return course;
	}

	@Bean(initMethod = "setup", destroyMethod = "cleanup")
	public Module module() {
		Module module = new Module();
		module.setAssignment(assignment());
		return module;
	}
	
	...
}		
public class Course {

	private Module module;
	private String name;
	
	public Course() {
	}
	
	public void setup() {
		this.name = "M100 Pythagoras Theorems"
	}
	
	public void setModule(Module module) {
		this.module = module;
	}
	
	public void cleanup() {
		module = null;
	}
}

The above code revisits the AppContext configuration class. The @Bean annotation has now two extra attributes viz. initMethod and destroyMethod. They define lifecycle methods setup and cleanup. These methods are implemented in the registered bean and eventually called by the container upon the bean initialization and before its destruction. The Course bean, taken as an example here, provides lifecycle method implementation. The methods implemented are setup and cleanup. Similarly you can also implement these methods in Module and Assignment beans.

Bean scopes

The scope of the bean can be defined with the @Scope annotation. The XML way of doing was to specify the scope attribute in the bean element

Listing 9. Using XML approach to define bean scope
<bean id="course" class="demo.Course" scope="prototype" >
	<property name="module" ref="module"/>
</bean>

The following code illustrates scope definition for a bean using Java configuration

Listing 10. Using AppContext config clas to define bean scope
@Configuration
public class AppContext {
	@Bean(initMethod = "setup", destroyMethod = "cleanup")
	@Scope("prototype")
	public Course course() {
		Course course = new Course();
		course.setModule(module());
		return course;
	}
	...
}

As you see from the above code, its pretty straightforward to define the scope of the bean in the Java configuration class. The AppContext configuration class above defines a prototype scope for the Course bean using @Scope annotation. The default scope is singleton.

There are plenty of things you can do with Java configuration. The article has only touch based on the basics. There is no great advantage in using Java configuration. It is just an alternative to XML configuration provided by Spring. Those who do not prefer XMLs in their framework, this is a nice way to approach a configuration. The downside is ofcourse you have to re-compile the application if you make any changes to the configuration in your Java class.

Resources

Learn

Get products and technologies

  • Evaluate IBM products in the way that suits you best: Download a product trial, try a product online, use a product in a cloud environment, or spend a few hours in the SOA Sandbox learning how to implement Service Oriented Architecture efficiently.

Discuss

  • Get involved in the My developerWorks community. Connect with other developerWorks users while exploring the developer-driven blogs, forums, groups, and wikis.

Comments

developerWorks: Sign in

Required fields are indicated with an asterisk (*).


Need an IBM ID?
Forgot your IBM ID?


Forgot your password?
Change your password

By clicking Submit, you agree to the developerWorks terms of use.

 


The first time you sign into developerWorks, a profile is created for you. Information in your profile (your name, country/region, and company name) is displayed to the public and will accompany any content you post, unless you opt to hide your company name. You may update your IBM account at any time.

All information submitted is secure.

Choose your display name



The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerWorks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

Required fields are indicated with an asterisk (*).

(Must be between 3 – 31 characters.)

By clicking Submit, you agree to the developerWorks terms of use.

 


All information submitted is secure.

Dig deeper into SOA and web services on developerWorks


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=SOA and web services
ArticleID=741686
ArticleTitle=Spring bean management using Java configuration
publish-date=07192011