What is the Spring Framework?
According to SpringFramework.org:
Spring provides a light-weight solution for building enterprise-ready
applications, while still supporting the possibility of using declarative
transaction management, remote access to your logic using RMI or web
services, and various options for persisting your data to a database [1].
More specifically Spring is a way of using regular Java Beans as
Enterprise JavaBeans without involving the complexity of J2EE.
JavaBeans encapsulate many objects into a single object (the bean), so that
the bean can be passed around rather than the individual objects [2].
The Enterprise JavaBean (EJB) is a managed, server-side component
architecture for modular construction of enterprise applications [3],
which requires a J2EE container/application server. Java 2 Enterprise
Edition (J2EE) is a combination of libraries and useful technologies
for the Java programming language, that are used to develop and deploy
enterprise applications using modular components using a Java application
server.
Spring is more than just JavaBeans though, it is a framework that contains
other frameworks, which are designed to independently work well with other
frameworks. These frameworks or modules are typically divided into the following:
- Inversion of Control Container (Core Container)
- Context Module
- Aspect Oriented Programming (AOP) Module
- Data Access Object (DAO) Module
- Object-Relational Mapping (ORM) Module
- Web Module
- Model-View-Controller (MVC) Framework
For the purposes of introduction though, it is best to start with the basics
of the Inversion Control Container. Central in the Spring Framework is
its Inversion of Control Container that provides a consistent means of
configuring and managing Java objects. This container is also known as
BeanFactory, ApplicationContext or Core container [4].
Inversion of Control is a concept in which the control flow is inverted
compared to the traditional interaction model expressed in imperative style by a
series of procedure calls. Thus, instead of the programmer specifying, by the
means of function calls, a series of events to happen during the lifetime of a
programme, they would rather register desired responses to particular
happenings, and then let some external entities take over the control over the
precise order and set of events to happen [5].
Where do I get the Spring Framework and how do I install it?
The framework is a series of JAR files, which can be downloaded from
http://www.springframework.org/download for fee. To install it all you
really have to do is extract the downloaded compressed file to some location on
your computer, and then reference the appropriate JARs in a Java project. If you
download the full distribution you will get the following directories, which are
specified "RELEASE INFO" section of the "readme.txt" included with the
distribution:
- dist - contains the Spring distribution jar files, as well as a
zip of all Java source files
- docs - contains the Spring reference documentation in PDF and HTML
format, as well as the complete API javadocs
- lib - contains all third-party libraries needed for building the
framework and/or running the samples
- src - contains the general Java source files for the framework
- mock - contains the general Java source files for Spring's mock
and test classes
- test - contains the general Java source files for Spring's test
suite
- tiger/src - contains the JDK-1.5-specific Java source files for the
framework
- tiger/test - contains the JDK-1.5-specific Java source files for
Spring's test suite
- aspectj/src - contains the AspectJ-specific source files for the
framework
- aspectj/test - contains the AspectJ-specific source files for Spring's
test suite
- samples - contains various demo applications and showcases
How do I use the Spring Framework?
Considering that there are many sub-frameworks in Spring, it is easiest to
start with an example that demonstrates the core basics of the Inversion of
Control Container. There are many available Spring Tutorials that can be
found in books and on the internet. So far the best example that I have been
able to find is the Inversion of Control example from DevelopersBook.com,
in which you don't directly connect your components and
services together in code but describe which services are needed by which
components in a configuration file [6]. I have taken the basic
example and modified it to include comments and a few other properties, with the
intention for later use in an Aspect Oriented Programming example. Consider a simple application framework that provides JavaBean that is used to greet as specified person using a "Greeting Service,"
and say good-bye to that person using a "Leaving Service." This requires the
following classes, interfaces, and XML configuration:
- HelloBean.java - This is the bean that is used to encapsulate the
"Greeting Service" and "Leaving Service."
- HelloBean.xml - This is the Spring XML configuration file that is
used to specify the instance and relationships of the involved object.
- GreetingService.java (implementing GreetingInterface.java)
- This is the service that is used to generate the greeting message.
- LeavingService.java (implementing LeavingInterface.java) -
This is the service that is used to generate the leaving message.
- HelloClient.java - This is the main class that uses the
Inversion of Control Container with the Spring XML configuration file to
get the specified instance of the HelloBean.
The following is the project directory structure, which shows the location of
the Java source code files, the related class files, and the Spring XML
configuration file:
- bin
- springapp
- service
- interfaces
- GreetingInterface.class
- LeavingInterface.class
- GreetingService.class
- LeavingService.class
- bean
- HelloClient.class
- HelloBean.xml
- src
- springapp
- service
- interfaces
- GreetingInterface.java
- LeavingInterface.java
- GreetingService.java
- LeavingService.java
- bean
- HelloClient.java
Architecturally the following class diagram shows how all of the objects
relate to one another within the "springapp" package:
The "HelloClient" uses the Spring XML configuration file "HelloBean.xml" with
the Inversion of Control Container to create the specified instance of
the "HelloBean." The "HelloBean" encapsulates the objects and functionality of
the "GreetingService" and "LeavingService."
For this particular application, the following libraries from the Spring
Framework are required:
- <spring-install>\lib\jakarta-commons\*.jar
- <spring-install>\lib\log4j\lg4j-1.2.14.jar
- <spring-install>\dist\spring.jar
GreetingService.java
This is an object that is instantiated by the "HelloBean" in order to
generate the greeting message. The actual instantiation though is specified in
the "HelloBean.xml" file, which is handled by the Inversion of Control
Container or BeanFactory. This class only has one property, which is
the variable "greetingMessage." In order for the BeanFactory to be able
to allow the setting of the value of this variable the class must provide a
"setter" method. In the case of the "GreetingService," it has a "setGreetingMessage"
method that can used by the BeanFactory to set the value of the "greetingMessage"
variable.
package springapp.service;
import springapp.service.interfaces.GreetingInterface;
/**
* <p>Title: Greeting Service</p>
*
* <p>Description: This is the service that is used to generate
* the greeting message.</p>
* <p>Taken and modified from Code Listing 1:
* http://www.developersbook.com/spring/spring-tutorials/</p>
*
* @author John Valentino II
*/
public class GreetingService implements GreetingInterface {
/** This is greeting message that is displayed.*/
private String greetingMessage;
/**
* Returns the "Hello" message for the person of the given name.
* @param name
* @return String
*/
public String sayHello(String name) {
return greetingMessage + " " + name + ".";
}
/**
* Sets the greeting message
* @param message
*/
public void setGreetingMessage(String message) {
this.greetingMessage = message;
}
}
GreetingInterface.java
The methods required to be implemented by the "GreetingService" that are
public and are not "getter" or "setter" methods are specified in this interface.
This is because it is considered good practice to separately specify those
methods in an implemented interface.
package springapp.service.interfaces;
/**
* <p>Title: Greeting Interface</p>
*
* <p>Description: Representing the methods of the Greeting Service.</p>
* <p>Taken and modified from Code Listing 1:
* http://www.developersbook.com/spring/spring-tutorials/</p>
*
* @author John Valentino II
*/
public interface GreetingInterface {
/**
* Returns the "Hello" message for the person of the given name.
* @param name
* @return String
*/
public String sayHello(String name);
}
LeavingService.java
This is an object that is instantiated by the "HelloBean" in order to
generate the leaving message. The actual instantiation though is specified in
the "HelloBean.xml" file, which is handled by the Inversion of Control
Container or BeanFactory. This class only has one property, which is
the variable "leavingMessage." In order for the BeanFactory to be able to
allow the setting of the value of this variable the class must provide a
"setter" method. In the case of the "LeavingService," it has a "setLeavingMessage"
method that can used by the BeanFactory to set the value of the
"leavingMessage" variable.
package springapp.service;
import springapp.service.interfaces.LeavingInterface;
/**
* <p>Title: Leaving Service</p>
*
* <p>Description: This is the service that is used to generate
* the leaving message.</p>
* <p>Taken and modified from Code Listing 2:
* http://www.developersbook.com/spring/spring-tutorials/</p>
*
* @author John Valentino II
*/
public class LeavingService implements LeavingInterface {
/** The good-bye message to be displayed. */
private String leavingMessage;
/**
* Returns the "Good-Bye" message for the person of the given name
* @param name
* @return String
*/
public String sayGoodBye(String name) {
return leavingMessage + " " + name + ".";
}
/**
* Sets the good-bye message
* @param message
*/
public void setLeavingMessage(String message) {
this.leavingMessage = message;
}
}
LeavingInterface.java
The methods required to be implemented by the "LeavingService" that are
public and are not "getter" or "setter" methods are specified in this interface.
package springapp.service.interfaces;
/**
* <p>Title: Leaving Interface</p>
*
* <p>Required methods for the Leaving Service.</p>
* <p>Taken and modified from Code Listing 2:
* http://www.developersbook.com/spring/spring-tutorials/</p>
*
* @author John Valentino II
*
*/
public interface LeavingInterface {
/**
* Returns the "Good-Bye" message for the person of the given name
* @param name
* @return String
*/
public String sayGoodBye(String name);
}
HelloBean.java
This is the JavaBean that is used to encapsulate the services of this
example application. Since this class has three properties, it specifies three
"setter" methods to allow the setting of instances or values by the
BeanFactory or other parent classes.
package springapp.bean;
import springapp.service.GreetingService;
import springapp.service.LeavingService;
/**
* <p>Title: Hello Bean</p>
*
* <p>Description: Represents the Hello Bean.</p>
* <p>Taken and modified from Code Listing 4:
* http://www.developersbook.com/spring/spring-tutorials/</p>
*
* @author John Valentino II
*/
public class HelloBean {
/** Represents the service used to generate a greeting */
private GreetingService greetingService;
/** Represents the service used to generate a good-bye message */
private LeavingService leavingService;
/** Represents the name of the person to meet or leave */
private String personName;
/**
* Sets the name of the person
* @param name
*/
public void setPersonName(String name) {
this.personName = name;
}
/**
* Sets the instance of the greeting service
* @param service
*/
public void setGreetingService(GreetingService service) {
this.greetingService = service;
}
/**
* Set the instance of the leaving service
* @param service
*/
public void setLeavingService(LeavingService service) {
this.leavingService = service;
}
/**
* Generates the greeting message
* @return
*/
public String greet() {
return greetingService.sayHello(personName);
}
/**
* Generates the leaving message
* @return
*/
public String leave() {
return leavingService.sayGoodBye(personName);
}
}
HelloClient.java
This is the main class of the application that uses the "HelloBean.xml" with
the Inversion of Control Container to create the instance of the "HelloBean"
and call is available methods.
package springapp;
import springapp.bean.HelloBean;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* <p>Title: Hello Client</p>
*
* <p>Description: Represents a program that uses the HelloBean.</p>
* <p>Taken and modified from Code Listing 5:
* http://www.developersbook.com/spring/spring-tutorials/</p>
*
* @author John Valentino II
*/
public class HelloClient {
/**
* @param args
*/
public static void main(String[] args) {
//Get the instance of the HelloBean as specified in HelloBean.xml
ClassPathXmlApplicationContext appContext =
new ClassPathXmlApplicationContext(new String[] { "HelloBean.xml" });
HelloBean helloBean = (HelloBean) appContext.getBean("helloBean");
System.out.println(helloBean.greet());
System.out.println(helloBean.leave());
}
}
HelloBean.xml
This is the Spring XML configuration file that is used to specify the
instances and properties of the bean classes within the application.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
"http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
<!-- Creates an instance of the "HelloBean" class -->
<bean id="helloBean" class="springapp.bean.HelloBean">
<!-- Sets the value of "personName" by
calling "setPersonName" -->
<property name="personName">
<value>Sarah</value>
</property>
<!-- Sets the instance of "greetingService" by
calling "setGreetingService" -->
<property name="greetingService">
<ref bean="greetingService" />
</property>
<!-- Sets the instance of "leavingService" by
calling "setLeavingService" -->
<property name="leavingService">
<ref bean="leavingService" />
</property>
</bean>
<!-- Creates an instance of the "GreetingService" -->
<bean id="greetingService" class="springapp.service.GreetingService">
<!-- Sets the value of "greetingMessage" by
calling "setGreetingMessage" -->
<property name="greetingMessage">
<value>Hello</value>
</property>
</bean>
<!-- Creates an instance of the "LeavingService" -->
<bean id="leavingService" class="springapp.service.LeavingService">
<!-- Sets the value of "leavingMessage" by
calling "setLeavingMessage" -->
<property name="leavingMessage">
<value>Good-bye</value>
</property>
</bean>
</beans>
Output
The program runs and generates the following output:
Hello Sarah.
Good-bye Sarah.
This output is to be expected as the Spring XML configuration file specifies
that the "HelloBean" instance has the specified "personName," an instance of the
"GreetingService," and an instance of the "LeavingService." Both service
instances are also given specified "greetingMessage" and "leavingMessage"
values.
Links
References
- SpringFramework.org, Documentation Preface,
http://static.springframework.org/spring/docs/2.0.x/reference/preface.html
- Wikipedia, JavaBean,
http://en.wikipedia.org/wiki/JavaBeans
- Wikipedia, Enterprise JavaBean,
http://en.wikipedia.org/wiki/Ejb
- Wikipedia, Spring Framework,
http://en.wikipedia.org/wiki/Spring_framework
- Wikipedia, Inversion of Control,
http://en.wikipedia.org/wiki/Inversion_of_Control
- DevlopersBook.com, Spring Framework Tutorial,
http://www.developersbook.com/spring/spring-tutorials/spring-tutorials.php