Sridhar Yerramreddy's Weblog

Icon

Architecture is the only answer!!

Why Spring Framework?

Spring Framework provides remarkable improvements in developer productivity, runtime performance, and overall application quality. Its unique blend of a complete, lightweight container that allows you to build a complex application from loosely-coupled POJOs and a set of easily understood abstractions that simplify construction, testing, and deployment make Spring both powerful and easy-to-use—a hard-to-beat combination. With this power comes the potential for a wide range of uses in both common and not-so-common scenarios.

Spring enables you to enjoy the key benefits of JEE, while minimizing the complexity encountered by application code.The essence of Spring is in providing enterprise services to Plain Old Java Objects (POJOs). This is particularly valuable in a JEE environment, but application code delivered as POJOs is naturally reusable in a variety of runtime environments.

Spring in Context

Spring is a manifestation of a wider movement. Spring is the most successful product in what can broadly be termed agile JEE.

Technologies

While Spring has been responsible for real innovation, many of the ideas it has popularized were part of the zeitgeist and would have become important even had there been no Spring project. Spring’s greatest contribution — besides a solid, high quality, implementation — has been its combination of emerging ideas into a coherent whole, along with an overall architectural vision to facilitate effective use.

Inversion of Control and Dependency Injection

The technology that Spring is most identified with is Inversion of Control (or IoC), and specifically theDependency Injection flavor of IoC. Spring is often thought of as an Inversion of Control container, although in reality it is much more.

Inversion of Control is best understood through the term the “Hollywood Principle,” which basically means “Don’t call me, I’ll call you.” Consider a traditional class library: Application code is responsible for the overall flow of control, calling out to the class library as necessary. With the Hollywood Principle, framework code invokes application code, coordinating overall workflow, rather than application code invoking framework code.

IoC is a broad concept, and can encompass many things, including the EJB and Servlet model, and the way in which Spring uses callback interfaces to allow clean acquisition and release of resources such as JDBC Connections.

Spring’s flavor of IoC for configuration management is rather more specific. Consequently, Martin Fowler, Rod Johnson, Aslak Hellesoy, and Paul Hammant coined the name Dependency Injection in late 2003 to describe the approach to IoC promoted by Spring, PicoContainer, and HiveMind-the three most popular lightweight frameworks.

Dependency Injection is based on Java language constructs, rather than the use of framework-specific interfaces. Instead of application code using framework APIs to resolve dependencies such as configuration parameters and collaborating objects, application classes expose their dependencies through methods or constructors that the framework can call with the appropriate values at runtime, based on configuration.

Dependency Injection is a form of push configuration; the container “pushes” dependencies into application objects at runtime. This is the opposite of traditional pull configuration, in which the application object “pulls” dependencies from its environment. Thus, Dependency Injection objects never load custom properties or go to a database to load configuration — the framework is wholly responsible for actually reading configuration.

Push configuration has a number of compelling advantages over traditional pull configuration. For example, it means that:

  • Application classes are self-documenting, and dependencies are explicit. It’s merely necessary to look at the constructors and other methods on a class to see its configuration requirements. There’s no danger that the class will expect its own undocumented properties or other formats.
  • For the same reason, documentation of dependencies is always up-to-date.
  • There’s little or no lock-in to a particular framework, or proprietary code, for configuration management. It’s all done through the Java language itself.
  • As the framework is wholly responsible for reading configuration, it’s possible to switch where configuration comes from without breaking application code. For example, the same application classes could be configured from XML files, properties files, or a database without needing to be changed.
  • As the framework is wholly responsible for reading configuration, there is usually greater consistency in configuration management. Gone are the days when each developer will approach configuration management differently.
  • Code in application classes focuses on the relevant business responsibilities. There’s no need to waste time writing configuration management code, and configuration management code won’t obscure business logic. A key piece of application plumbing is kept out of the developer’s way.

Developers who try Dependency Injection rapidly become hooked. These advantages are even more apparent in practice than they sound in theory.

Spring supports several types of Dependency Injection, making its support more comprehensive than that of any other product:

  • Setter Injection: The injection of dependencies via JavaBean setter methods. Often, but not necessarily, each setter has a corresponding getter method, in which case the property is set to be writable as well as readable.
  • Constructor Injection: The injection of dependencies via constructor arguments.
  • Method Injection: A more rarely used form of Dependency Injection in which the container is responsible for implementing methods at runtime. For example, an object might define a protected abstract method, and the container might implement it at runtime to return an object resulting from a container lookup. The aim of Method Injection is, again, to avoid dependencies on the container API.

Uniquely, Spring allows all three to be mixed when configuring one class, if appropriate.

Enough theory — take look at a simple example of an object being configured using Dependency Injection.

Assume that there is an interface — in this case, Service — which callers will code against. In this case, the implementation will be called ServiceImpl. However, of course the name is hidden from callers, who don’t know anything about how the Service implementation is constructed.

Assume that this implementation of Service has two dependencies: an int configuration property, setting a timeout; and a DAO that it uses to obtain persistent objects.

With Setter Injection you can configure ServiceImpl using JavaBean properties to satisfy these two dependencies, as follows:

public class ServiceImpl implements Service {
 private int timeout;
 private AccountDao accountDao;

   public void setTimeout(int timeout) {
     this.timeout = timeout;
   }

   public void setAccountDao(AccountDao accountDao) {
     this.accountDao = accountDao;
   }

With Constructor Injection, you supply both properties in the Constructor, as follows:

public class ServiceImpl implements Service {
 private int timeout;
 private AccountDao accountDao;

   public ServiceImpl (int timeout, AccountDao accountDao) {
       this.timeout = timeout;
       this.accountDao = accountDao;
   }

Either way, the dependencies are satisfied by the framework before any business methods onServiceImpl are invoked. (For brevity, there are business methods shown in the code fragments. Business methods will use the instance variables populated through Dependency Injection.)

This may seem trivial. You may be wondering how such a simple concept can be so important. While it is conceptually simple, it can scale to handle complex configuration requirements, populating whole object graphs as required. It’s possible to build object graphs of arbitrary complexity using Dependency Injection. Spring also supports configuration of maps, lists, arrays, and properties, including arbitrary nesting.

As an IoC container takes responsibility for object instantiation, it can also support important creational patterns such as singletons, prototypes, and object pools. For example, a sophisticated IoC container such as Spring can allow a choice between “singleton” or shared objects (one per IoC container instance) and non-singleton or “prototype” instances (of which there can be any number of independent instances).

Because the container is responsible for satisfying dependencies, it can also introduce a layer of indirection as required to allow custom interception or hot swapping. (In the case of Spring, it can go a step farther and provide a true AOP capability. Thus, for example, the container can satisfy a dependency with an object that is instrumented by the container, or which hides a “target object” that can be changed at runtime without affecting references. Unlike some IoC containers and complex configuration management APIs such as JMX, Spring does not introduce such indirection unless it’s necessary. In accordance with its philosophy of allowing the simplest thing that can possibly work, unless you want such features, Spring will give you normal instances of your POJOs, wired together through normal property references. However, it provides powerful indirection capabilities if you want to take that next step.

Spring also provides many hooks that allow power users to customize how the container works. As with the optional lifecycle callbacks, you won’t often need to use this capability, but it’s essential in some advanced cases, and is the product of experience using IoC in many demanding scenarios.

The key innovation in Dependency Injection is that it works with pure Java syntax: no dependence on container APIs is required.

Dependency Injection is an amazingly simple concept, yet, with a good container, it’s amazingly powerful. It can be used to manage arbitrarily fine-grained objects; it places few constraints on object design; and it can be combined with container services to provide a wide range of value adds.

You don’t need to do anything in particular to make an application class eligible for Dependency Injection — that’s part of its elegance. In order to make classes “good citizens,” you should avoid doing things that cut against the spirit of Dependency Injection, such as parsing custom properties files. But there are no hard and fast rules. Thus there is a huge potential to use legacy code in a container that supports Dependency Injection, and that’s a big win.

Aspect-Oriented Programming

Dependency Injection goes a long way towards delivering the ideal of a fully featured application framework enabling a POJO programming model. However, configuration management isn’t the only issue; you also need to provide declarative services to objects. It’s a great start to be able to configure POJOs-even with a rich network of collaborators-without constraining their design; it’s equally important to be able to apply services such as transaction management to POJOs without them needing to implement special APIs.

The ideal solution is Aspect-Oriented Programming (AOP). (AOP is also a solution for much more; besides, this article refers to a particular use of AOP, rather than the end all and be all of AOP.)

AOP provides a different way of thinking about code structure, compared to OOP or procedural programming. Whereas in OOP you model real-world objects or concepts, such as bank accounts, as objects, and organize those objects in hierarchies, AOP enables you to think about concerns or aspectsin your system. Typical concerns are transaction management, logging, or failure monitoring. For example, transaction management applies to operations on bank accounts, but also to many other things besides. Transaction management applies to sets of methods without much relationship to the object hierarchy. This can be hard to capture in traditional OOP. Typically you end up with a choice of tradeoffs:

  • Writing boilerplate code to apply the services to every method that requires them: Like all cut-and-paste approaches, this is unmaintainable; if you need to modify how a service is delivered, you need to change multiple blocks of code, and OOP alone can’t help you modularize that code. Furthermore, each additional concern will result in its own boilerplate code, threatening to obscure the business purpose of each method. You can use the Decoratordesign pattern to keep the new code distinct, but there will still be a lot of code duplication. In a minority of cases the Observer design pattern is sufficient, but it doesn’t offer strong typing, and you must build in support for the pattern by making your objects observable.
  • Detype operations, through something like the Command pattern: This enables a custom interceptor chain to apply behavior such as declarative transaction management, but at the loss of strong typing and readability.
  • Choosing a heavyweight dedicated framework such as EJB that can deliver the necessary services: This works for some concerns such as transaction management, but fails if you need a custom service, or don’t like the way in which the EJB specification approaches the particular concern. For example, you can’t use EJB services if you have a web application that should ideally run in a web container, or in case of a standalone application with a Swing GUI. Such frameworks also place constraints on your code-you are no longer in the realm of POJOs.

In short, with a traditional OO approach the choices are code duplication, loss of strong typing, or an intrusive special-purpose framework.

AOP enables you to capture the cross-cutting code in modules such as interceptors that can be applied declaratively wherever the concern they express applies — without imposing tradeoffs on the objects benefiting from the services.

Spring AOP allows the proxying of interfaces or classes. It provides an extensible pointcut model, enabling identification of which sets of method to advise. It also supports introduction: advice that makes a class implement additional interfaces. Introduction can be very useful in certain circumstances (especially infrastructural code within the framework itself).

Here, the interest lies in the value proposition that Spring AOP provides and why it’s key to the overall Spring vision.

Spring AOP is used in the framework itself for a variety of purposes, many of which are behind the scenes and which many users may not realize are the result of AOP:

  • Declarative transaction management: This is the most important out-of-the-box service supplied with Spring.
    * It can be applied to any POJO.
    * It isn’t tied to JTA, but can work with a variety of underlying transaction APIs (including JTA). Thus it can work in a web container or standalone application using a single database, and doesn’t require a full J2EE application server.
    * It supports additional semantics that minimize the need to depend on a proprietary transaction API to force rollback.
  • Hot swapping: An AOP proxy can be used to provide a layer of indirection. (Remember the discussion of how indirection can provide a key benefit in implementing Dependency Injection?) For example, if an OrderProcessor depends on an InventoryManager, and theInventoryManager is set as a property of the OrderProcessor, it’s possible to introduce a proxy to ensure that the InventoryManager instance can be changed without invalidating theOrderProcessor reference. This mechanism is threadsafe, providing powerful “hot swap” capabilities. Full-blown AOP isn’t the only way to do this, but if a proxy is to be introduced at all, enabling the full power of Spring AOP makes sense.
  • “Dynamic object” support: As with hot swapping, the use of an AOP proxy can enable “dynamic” objects such as objects sourced from scripts in a language such as Groovy or Beanshell to support reload (changing the underlying instance) and (using introduction) implement additional interfaces allowing state to be queried and manipulated (last refresh, forcible refresh, and so on).
  • Security: Acegi Security for Spring is an associated framework that uses Spring AOP to deliver a sophisticated declarative security model.
Advertisement

Filed under: SDLC

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.