Tuesday, February 22, 2011

Bean Definitions for Spring Framework

Introduction
I am discussing various ways of defining beans for Spring framework. What I will cover is the approach, tricks and importance of correctly defining the beans for Spring framework.

Why are Beans important for applications using Spring framework?
Spring framework’s core features are around dependency injection and beans lifecycle management. What this means is that programmers don’t write code to inject bean definitions. Instead Spring framework injects the dependency to beans. Spring framework container manages this with the help of XML configuration files and Java reflection. Developers have to write code for the Java beans and create XML files for injecting dependencies in the beans.

Constructor based bean instantiation:
I have shown below XML configuration file – beans1.xml and beans2.xml:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
                <!-- services -->
                <bean id="petStore"
                                class="org.springframework.samples.jpetstore.services.PetStoreServiceImpl">
                                                <property name="accountDao" ref="accountDao"/>
                                                <property name="itemDao" ref="itemDao"/>
                                                <!-- additional collaborators and configuration for this bean go here -->
                </bean>
                <!-- more bean definitions for services go here -->
</beans>



Beans2.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
                <bean id="accountDao"
                                class="org.springframework.samples.jpetstore.dao.ibatis.SqlMapAccountDao">
                <!-- additional collaborators and configuration for this bean go here -->
                </bean>
                <bean id="itemDao"                                                      class="org.springframework.samples.jpetstore.dao.ibatis.SqlMapItemDao">
                                <!-- additional collaborators and configuration for this bean go here -->
                </bean>
                <!-- more bean definitions for data access objects go here -->
</beans>

This is a simple XML file which will be used by Spring IoC container to instantiate the beans defined in the XML file. To instantiate the Spring container, use the following code:
ApplicationContext context =
                new ClassPathXmlApplicationContext(new String[] {"beans1.xml", "beans2.xml"});


The developers write the above Java code to instantiate the Spring IoC container with the Spring’s ApplicationContext class and passing the xml files as arguments.

Instantiation with a static factory method:
Beans can be defined to be instantiated from a static factory method instantiation. This can  be done by providing a static method in the Java class and giving factory-method as attribute in the Spring XML file. See the example below:
<bean id="clientService" class="examples.ClientService"              factory-method="createInstance"/>


public class ClientService {
                private static ClientService clientService = new ClientService();

                private ClientService() {}

                public static ClientService createInstance() {
                                return clientService;
                }
}




Instantiation using an instance factory method:
Beans can be defined to be instantiated from an instance factory method. This can be done providing a instance factory method in the Java class and giving factory-method as in the Spring XML file. See the example below:
<bean id="serviceLocator" class="examples.DefaultServiceLocator">
                <!-- inject any dependencies required by this locator bean -->
</bean>

<bean id="clientService"  factory-bean="serviceLocator"
                                                factory-method="createClientServiceInstance"/>

<bean id="accountService"
                                factory-bean="serviceLocator"
                                                factory-method="createAccountServiceInstance"/>


public class DefaultServiceLocator {

                private static ClientService clientService = new ClientServiceImpl();
               
                private static AccountService accountService = new AccountServiceImpl();
               
                private DefaultServiceLocator() {}
               
                public ClientService createClientServiceInstance() {
                                return clientService;
                }

                public AccountService createAccountServiceInstance() {
                                return accountService;
                }
}


The above approach shows that the lifecycle of the factory bean itself can be managed by the Spring IoC container.

Dependency Injection (DI):
DI is a process of Spring container injecting dependency of one object to other objects automatically without the need for object to construct the other object or need for the object to know other object’s location.
There are two variants of DI, Constructor based DI and Setter based DI.

Constructor-based DI:
Constructor based DI is accomplished by the container invoking a constructor with a number of arguments, each representing a dependency.  See the example below:
package examples;
               
                public class ExampleBean {
                // No. of years to the calculate the Ultimate Answer

                private int years;
                // The Answer to Life, the Universe, and Everything
               
                private String ultimateAnswer;

                public ExampleBean(int years, String ultimateAnswer) {
                                this.years = years;
                                this.ultimateAnswer = ultimateAnswer;
                }
}


<bean id="exampleBean" class="examples.ExampleBean">
                <constructor-arg index="0" value="7500000"/>
                <constructor-arg index="1" value="42"/>
</bean>

The above XML shows the index attribute to identify the correct parameter to the constructor.

Setter based DI:
Setter based DI is accomplished by the container after calling the no-arg constructor or a static factory method and calling the setter methods to inject the dependency.
See the example below:
public class SimpleMovieLister {
                // the SimpleMovieLister has a dependency on the MovieFinder

                private MovieFinder movieFinder;

                // a setter method so that the Spring container can 'inject' a MovieFinder
                public void setMovieFinder(MovieFinder movieFinder) {
                                this.movieFinder = movieFinder;
                }
                // business logic that actually 'uses' the injected MovieFinder is omitted...
}

There are many more forms of bean definitions with benas accepting collection classes like Map, List, Set, etc.
For more information and reference please visit the URL - http://www.springsource.org/ . The web site has many tutorials and information on setting up Spring framework.