A Quick Introduction to the Spring Python Framework
The original Spring, written for Java, is a framework which at its heart uses an "Inversion of Control" container (IoC). Inside of Spring, are several subframeworks for handling aspect oriented programming(aop), Data Access Framework (Dao), transaction management, a object to relational mapping(orm), and other features. The SpringPython framework, is a port of the original Java framework. Mind you, the developers of SpringPython didn't do a "direct port of existing code" from the Java counterpart, but rather rewrote it using Python idioms. SpringPython includes features for:
- Database Template
- Database Transactions
- Plugins/Command Line Tools
As with the Java version, Spring Python includes some samples; Petclinic, Spring Wiki, and Spring Bot. This article will cover mostly the basic use of the Inversion Of Control container. The purpose of this article is to get you up and using SpringPython quickly without having to parse the in depth theory.
To get started, you will need Pyro (Python Remote Objects) from http://pyro.sourceforge .net, which is "an object-oriented form of RPC". Think, a Python version of Remote Method Invocation (RMI). You will also need Amara from http://wiki.xml3k.org/ Amara for XML processing. Amara itself has some dependencies, so if you want to make your life easier I highly recommend downloading and installing Setuptools from http://pypi .python.org/pypi/setuptools. Setuptools has easy_install which will take care of the dependencies.
$ sudo easy_install Amara-188.8.131.52-py2.5.egg
Listing 1. The dollar sign represents the Linux command line.
Inversion of Control and Dependency Injection
Inversion of Control is a design pattern that applies the Hollywood principle, "Don't call us, we'll call you", in other words, the flow of control of a system is inverted. Using an adapted example from Martin Fowler, in a simple program that gets input from the command line, the program holds the control. Here, my program controls the flow.
name = raw_input('What is your name? ') doSomethingWithName(name) quest = raw_input('What is your quest? ') doSomethingWithQuest(quest)
Listing 2. A simple procedural program that accepts some input, and processes the information. Martin Fowler's original example uses Ruby.
In a GUI run program, the control is held by the windowing system. Again paraphrasing Martin Fowler's example, with Python and Tkinter:
from Tkinter import * def process_name(name): print "name is ", name def process_quest(quest): print "quest is ", quest root = Tk() name_label = Label(root, text="What is Your Name?").pack() name = Entry(root) name.bind("<FOCUSOUT>", (lambda event: process_name(name.get()))) name.pack() quest_label = Label(root, text="What is Your Quest?").pack() quest = Entry(root) quest.bind("<FOCUSOUT>", (lambda event : process_quest(quest.get()))) quest.pack() root.mainloop()
Listing 3. Instead of the program controlling the flow, now the windowing system takes the control
So, the flow of control was "Inverted"; instead of me doing the calling, the windowing system does the calling. Spring is known as a Inversion of Control container, abbreviated as IoC, with some added features, such as aspect oriented programming.
In the case of Spring, what's being inverted is the process of obtaining an external dependency. This is a special case of IoC is known as Dependency Injection, or DI. In other words, a dependency is "injected" into a component. In practice, as you're about to see, this is much simpler than it sounds.
The DI pattern has three parts; a dependent, its dependencies and an injector or container. Figure 1 illustrates this relationship. Objects A, B, and C (The dependencies) are injected into Component D (The dependant ) via the container.
Figure 1. A simplified illustration of dependency injection.
A great advantage to using this pattern is being able to feed a program mock objects, which can be replaced later, without having to change the code. This automatically lends itself well for unit testing.