Spring bean management using Java configuration
Learn to manage Spring beans using Java configuration
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.
Downloadable resources
Related topics
- Web service development with Apache CXF and Aegis Learn to develop a web service using CXF and Aegis databinding
- Design and implement POJO Web services using Spring and Apache CXF, Part 1: Introduction to Web services creation using CXF and Spring.
- Design and implement POJO Web services using Spring and Apache CXF, Part 2: Create a RESTful Web service
- Evaluate IBM products in the way that suits you best.