close

Spring is an open source framework created to address the complexity of enterprise application development. One of the chief advantages of the Spring framework is its layered architecture, which allows you to be selective about which of its components you use while also providing a cohesive framework for J2EE application development.

In this first article in my four-part Spring Series, I introduce you to the Spring framework. I start by describing the functionality of the framework in terms of its underlying modules and then discuss two of the most interesting modules, Spring aspect-oriented programming (AOP), and the Inversion of Control (IOC) container. I then use several examples to demonstrate the workings of the IOC container in a typical application use case scenario. The examples will also lay the foundation for an expanded discussion, later in this series, of the how the Spring framework implements AOP constructs through Spring AOP.

The Spring framework

The Spring framework is a layered architecture consisting of seven well-defined modules. The Spring modules are built on top of the core container, which defines how beans are created, configured, and managed, as shown in Figure 1.
Figure 1. The seven modules of the Spring framework
spring_framework

Each of the modules (or components) that comprise the Spring framework can stand on its own or be implemented jointly with one or more of the others. The functionality of each component is as follows:

  • The core container: The core container provides the essential functionality of the Spring framework. A primary component of the core container is the BeanFactory, an implementation of the Factory pattern. The BeanFactory applies the Inversion of Control (IOC) pattern to separate an application’s configuration and dependency specification from the actual application code.
  • Spring context: The Spring context is a configuration file that provides context information to the Spring framework. The Spring context includes enterprise services such as JNDI, EJB, e-mail, internalization, validation, and scheduling functionality.
  • Spring AOP: The Spring AOP module integrates aspect-oriented programming functionality directly into the Spring framework, through its configuration management feature. As a result you can easily AOP-enable any object managed by the Spring framework. The Spring AOP module provides transaction management services for objects in any Spring-based application. With Spring AOP you can incorporate declarative transaction management into your applications without relying on EJB components.
  • Spring DAO: The Spring JDBC DAO abstraction layer offers a meaningful exception hierarchy for managing the exception handling and error messages thrown by different database vendors. The exception hierarchy simplifies error handling and greatly reduces the amount of exception code you need to write, such as opening and closing connections. Spring DAO’s JDBC-oriented exceptions comply to its generic DAO exception hierarchy.
  • Spring ORM: The Spring framework plugs into several ORM frameworks to provide its Object Relational tool, including JDO, Hibernate, and iBatis SQL Maps. All of these comply to Spring’s generic transaction and DAO exception hierarchies.
  • Spring Web module: The Web context module builds on top of the application context module, providing contexts for Web-based applications. As a result, the Spring framework supports integration with Jakarta Struts. The Web module also eases the tasks of handling multi-part requests and binding request parameters to domain objects.
  • Spring MVC framework: The Model-View-Controller (MVC) framework is a full-featured MVC implementation for building Web applications. The MVC framework is highly configurable via strategy interfaces and accommodates numerous view technologies including JSP, Velocity, Tiles, iText, and POI.

Spring framework functionality can be used in any J2EE server and most of it also is adaptable to non-managed environments. A central focus of Spring is to allow for reusable business and data-access objects that are not tied to specific J2EE services. Such objects can be reused across J2EE environments (Web or EJB), standalone applications, test environments, and so on, without any hassle.


IOC and AOP

The basic concept of the Inversion of Control pattern (also known as dependency injection) is that you do not create your objects but describe how they should be created. 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. A container (in the case of the Spring framework, the IOC container) is then responsible for hooking it all up.

In a typical IOC scenario, the container creates all the objects, wires them together by setting the necessary properties, and determines when methods will be invoked. The three implementation pattern types for IOC are listed in the table below.

Type 1 Services need to implement a dedicated interface through which they are provided with an object from which they can look up dependencies (for example, additional needed services).
Type 2 Dependencies are assigned through JavaBeans properties (for example, setter methods).
Type 3 Dependencies are provided as constructor parameters and are not exposed as JavaBeans properties.

The Spring framework uses the Type 2 and Type 3 implementations for its IOC container.

Aspect-oriented programming

Aspect-oriented programming, or AOP, is a programming technique that allows programmers to modularize crosscutting concerns, or behavior that cuts across the typical divisions of responsibility, such as logging and transaction management. The core construct of AOP is the aspect, which encapsulates behaviors affecting multiple classes into reusable modules.

AOP and IOC are complementary technologies in that both apply a modular approach to complex problems in enterprise application development. In a typical object-oriented development approach you might implement logging functionality by putting logger statements in all your methods and Java classes. In an AOP approach you would instead modularize the logging services and apply them declaratively to the components that required logging. The advantage, of course, is that the Java class doesn’t need to know about the existence of the logging service or concern itself with any related code. As a result, application code written using Spring AOP is loosely coupled.

AOP functionality is fully integrated into the Spring context for transaction management, logging, and various other features.


The IOC container

The core of Spring’s design is the org.springframework.beans package, designed for use with JavaBean components. This package typically isn’t used directly by users, but serves as the underlying medium for much of the other functionality. The next-highest layer of abstraction is the BeanFactory interface, an implementation of the Factory design pattern that enables objects to be created and retrieved by name. BeanFactory can also manage relationships between objects.

BeanFactory supports two object modes.

  • Singleton mode provides a shared instance of the object with a particular name, which will be retrieved on lookup. Singleton is the default and most often used object mode. It is ideal for stateless service objects.
  • Prototype mode ensures that each retrieval will result in the creation of an independent object. Prototype mode would be best used in a case where each user needed to have his or her own object.

The bean factory concept is the foundation of Spring as an IOC container. IOC moves the responsibility for making things happen into the framework and away from application code. As I’ll show in the next examples, the Spring framework uses JavaBean properties and configuration data to figure out which dependencies must be set.

The BeanFactory interface

Because org.springframework.beans.factory.BeanFactory is a simple interface it can be implemented for a range of underlying storage methods. The most commonly used BeanFactory definition is the XmlBeanFactory, which loads beans based on definitions in an XML file, as shown in Listing 1.
Listing 1. XmlBeanFactory

BeanFactory factory = new XMLBeanFactory(new FileInputSteam("mybean.xml"));

Beans defined in XML files are lazily loaded, which means that the beans themselves will not be instantiated until they are needed. To retrieve a bean from BeanFactory you can simply call the getBean() method passing in the name of the bean you want to retrieve, as shown in Listing 2.
Listing 2. getBean()

MyBean mybean = (MyBean) factory.getBean("mybean");

Each bean definition can be a POJO (defined by class name and JavaBean initialization properties) or a FactoryBean. The FactoryBean interface adds a level of indirection to the applications built using the Spring framework.


An IOC example

The easiest way to understand inversion of control is to see it in action. I conclude this first article in the three-part Spring Series with an example that demonstrates how you can inject application dependencies (rather than build them in) through the Spring IOC container.

I’ll take the use case of opening an online credit card account as my starting point. With respect to the implementation, opening a credit card account requires that the user interact with the following services:

  • A credit rating service that queries the user’s credit history information
  • A remote credit linking service that inserts and links customer information with credit card and bank information for the purpose of automatic debits (if required)
  • An e-mail service that e-mails the user about the status of his credit card

Three interfaces

For this example, I assume that the services already exist and that it is desirable to integrate them in a loosely coupled manner. The listings below show the application interfaces for the three services.
Listing 3. CreditRatingInterface

public interface CreditRatingInterface {
public boolean getUserCreditHistoryInformation(ICustomer iCustomer);
}

The credit rating interface shown in Listing 3 provides credit history information. It requires a Customer object containing customer information. The implementation is provided by the CreditRating class.
Listing 4. CreditLinkingInterface

public interface CreditLinkingInterface {
public String getUrl();
public void setUrl(String url);
public void linkCreditBankAccount() throws Exception ;
}

The credit linking interface links credit history information with bank information (if required), and inserts credit card information for the user. The credit linking interface is a remote service whose lookup is made through the getUrl() method. The URL is set by the Spring framework’s beans configuration mechanism, which I discuss later. The implementation is provided by the CreditLinking class.
Listing 5. EmailInterface

public interface EmailInterface {
public void sendEmail(ICustomer iCustomer);
public String getFromEmail();
public void setFromEmail(String fromEmail) ;
public String getPassword();
public void setPassword(String password) ;
public String getSmtpHost() ;
public void setSmtpHost(String smtpHost);
public String getUserId() ;
public void setUserId(String userId);
}

The EmailInterface is responsible for sending e-mail to the customer regarding the status of his or her credit card. Mail configuration parameters such as SMPT host, user, and password are set by the previously mentioned beans configuration mechanism. The Email class provides the implementation.

Spring keeps it loose

With all the interfaces in place, the next thing to consider is how to integrate them in a loosely coupled manner. In Listing 6 you can see the implementation of the credit card account use case.
Listing 6. CreateCreditCardAccount

public class CreateCreditCardAccount implements
CreateCreditCardAccountInterface {

public CreditLinkingInterface getCreditLinkingInterface() { return creditLinkingInterface; } public void setCreditLinkingInterface( CreditLinkingInterface creditLinkingInterface) { this.creditLinkingInterface = creditLinkingInterface; } public CreditRatingInterface getCreditRatingInterface() { return creditRatingInterface; } public void setCreditRatingInterface(CreditRatingInterface creditRatingInterface) { this.creditRatingInterface = creditRatingInterface; } public EmailInterface getEmailInterface() { return emailInterface; } public void setEmailInterface(EmailInterface emailInterface) { this.emailInterface = emailInterface; } //Client will call this method public void createCreditCardAccount(ICustomer icustomer) throws Exception{ boolean crediRating getCreditRatingInterface().getUserCreditHistoryInformation(icustomer); icustomer.setCreditRating(crediRating); //Good Rating if(crediRating){ getCreditLinkingInterface().linkCreditBankAccount(icustomer); } getEmailInterface().sendEmail(icustomer);

}

Note that all the setter methods are implemented by Spring configuration beans. All the dependencies (that is, the three interfaces) can be injected by the Spring framework using these beans. The createCreditCardAccount() method will then use the services to carry out the remainder of the implementation.In Listing7 you can see the Spring configuration file. I used the arrows to highlight definitions.

Listing 7. The config file

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
"http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
<bean id="createCreditCard" -->define createCreditCard definition
class="springexample.creditcardaccount.CreateCreditCardAccount">
<property name="creditRatingInterface">-->inject creditRatingInterface dependency via creditRating reference bean
<ref bean="creditRating" />
</property>
<property name="creditLinkingInterface">">-->inject creditLinkingInterface dependency via creditLinking reference bean
<ref bean="creditLinking" />
<property name="emailInterface">">">-->inject emailInterface dependency via email reference bean
<ref bean="email" />
/property>
</bean>
<bean id="creditLinking">
<property name="url">
<value>http://localhost/creditLinkService</value>-->set url property value
</property>

Run the application

To run the example application you must first download the Spring framework and all its dependency files. Next, extract the framework to, say, <em>c:\</em> and a folder such as <em>C:\spring-framework-1.2-rc2</em> (for the current release version) will be created. You must also download and extract <a href=”http://ant.apache.org/” target=”_new”>Apache Ant</a> before continuing.

Next, extract the source code to a folder such as <em>c:\</em> and a <em>SpringProject</em> folder will be created. Copy the Spring libraries, namely <em>spring.jar</em> from <em>C:\spring-framework-1.2-rc2\dist</em> and <em>commons-logging.jar</em> from the <em>C:\spring-framework-1.2-rc2\lib\jakarta-commons</em> to the <em>SpringProject\lib</em> folder. With these things done, you have the necessary build dependencies set.

Open up the command prompt, change the directory to <em>SpringProject</em>, and type in the following at command prompt > build.

This will build and run the CreateCreditAccountClient class, which in turn will create a Customer class object and populate it and also call the CreateCreditCardAccount class to create and link the credit card account. The CreateCreditAccountClient will also load the Spring configuration files through ClassPathXmlApplicationContext. Once the beans are loaded, you can then access them through the getBean() method as shown, finally, in Listing 8.
<a name=”code8″><strong>Listing 8. Loading the Spring configuration file</strong></a>

ClassPathXmlApplicationContext appContext
new ClassPathXmlApplicationContext(new String[] {
"springexample-creditaccount.xml"
});

CreateCreditCardAccountInterface creditCardAccount (CreateCreditCardAccountInterface) appContext.getBean(“createCreditCard”);


In conclusion

In this first article of the four-part Spring Series I introduced you to the basics of the Spring framework. I started by discussing the seven modules that comprise Spring’s layered architecture and then offered a closer look at two of them: Spring AOP and the IOC container.

Since learning is best accomplished by doing, I then used a working example to show you how the IOC pattern (as implemented by the Spring IOC container) works to integrate disparate systems in a loosely coupled manner. In this example you saw how simple it was to inject dependencies, or services, into a working credit card account application rather than having to build them in from the ground up.

Stay tuned for the next article in this series, where I’ll build on what you learned here as I show you how the Spring AOP module provides persistence support in enterprise applications, as well as get you started with the Spring MVC module and related plug-ins.

This tutorial of mine was first published by IBM developerWorks. All rights reserved by IBM and Author.

Tags : aopspringspring tutorial
Naveen

The author Naveen