Fundamental Spring Concepts


We have covered a lot of introductory material on Spring already. However, this only reflects what Spring can do for you and how it is organized. We still need to cover some basic concepts that Spring is built on. Let's do that now before jumping into Spring code related to Time Expression (in the next chapter).

Dependency Injection Pattern (and IoC Containers)

In 2004, Martin Fowler published an article (http://www.martinfowler.com/articles/injection.html) discussing inversion of control (IoC) containers. Martin Fowler, some people involved with the PicoContainer, Rod Johnson (founder of the Spring Framework), and others collectively defined the dependency injection pattern. Dependency injection is a style of IoC; another style uses a template/callback technique. In both cases you are giving control to something else (hence, the term inversion of control). We will, of course, use the dependency injection style.

What is dependency injection exactly? Let's look at these two words separately. First, there is the dependency part; this basically translates into an association between two classes. For example, class A might need class B to get its job done. In other words, class A is dependent on class B. Now, let's look at the second part, injection. All this means is that class B will get injected into class A by the IoC container. This injection can happen in the way of passing parameters to the constructor or by post-construction using setter methods. (Both are described in more detail later in this chapter.)

Figure 6.4 shows an association between two classes we will see in our examples for Time Expression (in the next chapter). The associations shown in this diagram are exactly the dependencies we will map in the Spring application context file. In other words, TimesheetListController depends on TimesheetManager; hence, we will use Spring to automatically create a single instance of the TimesheetManager and inject (set) it via the TimesheetListController.setTimesheetManager method.

Figure 6.4. Sample association to use for determining bean class dependencies for use with Spring.


You might not be fully convinced of the benefits of using the design pattern approach for developing applications. However, after you begin working in this fashion, you probably won't want to go back to constructing objects using new statements, which not only clutters your Java code more than using dependency injection, but also couples your associated classes a bit more.

Two Injection Styles

There are two key types of dependency injection styles: one via arguments passed to the constructor when an object is created and the other via the setter methods of a JavaBean style class, after the object has been created.

Spring advocates the use of setter-based dependency injection (in the Spring Reference Documentation), because passing many arguments to the constructor can get cumbersome. Martin Fowler, on the other hand, argues (also at http://www.martinfowler.com/articles/injection.html) that if you have too many constructor arguments, your object might be too busy, and it's worth considering splitting the class up.

Although there are pros and cons to both approaches, considering that we are using Spring, we will go with Spring's recommendation and accordingly use setter-based injection for Time Expression. Also, I prefer the JavaBean style of injecting and obtaining property valuesthat is, using setters and getters. For some reason, this feels a bit more natural to me while coding in Java, but you might disagree. To further confuse things, the Pico Container team prefers the constructor-based injection and provides some valid reasons for it on their website (http://www.picocontainer.org/Why+Constructor+Injection).

Either way, it is nice to know that Spring supports both styles, which we will review shortly.

Note

Fowler also suggests a third type, interface injection, which isn't covered here, but you can read about it at http://www.martinfowler.com/articles/injection.html.


Beans, BeanFactory, and ApplicationContext

The org.springframework.beans.factory.BeanFactory interface is the actual IoC container! It is an interface that essentially manages the application's configuration by instantiating and managing beans defined via code or, in our case, XML files. Beans can be any type of objects, but commonly are JavaBean style classesthat is, classes with getters and setters.

The org.springframework.context.ApplicationContext essentially extends BeanFactory and adds additional facilities such as resource bundles, integration with Spring AOP, message resource handling, event broadcasting, and more. Furthermore, WebApplicationContext extends ApplicationContext by adding web application-specific context. Although you can use an implementation of the BeanFactory interface (for example, XmlBeanFactory), it is recommended that you use ApplicationContext for server-side applications.

This book's code zip file shows springtest-applicationcontext.xml, a sample Spring application context file. This example demonstrates both the setter-based injection using the <property> element and constructor-based injection using the <constructor-arg> element. In this example, notice that the bean springtestmessage depends on bean stringmessage, as shown here:

<bean           lazy-init="false" init-method="printMessage">     <property name="message" ref="stringmessage" /> </bean>


Notice also that we have an initialization method using the init-method attribute; this is a nice way to invoke initialization and termination methods on objects. This relationship (or association) is established using the <property> element and the injection occurs via the SpringTestMessage.setMessage method, as shown here:

public void setMessage(String message) {     this.message = message; }


Our SpringTest.java class (also in the book's code zip file) shows how simple it is to load an entire application context file and immediately begin using the various beans, with all the collaborator classes autowired by Spring's IoC container, as demonstrated here:

public static void main(String args[]) throws Exception {     FileSystemXmlApplicationContext factory =         new FileSystemXmlApplicationContext(             "src/conf/springtest-applicationcontext.xml");     SpringTestMessage stm = (SpringTestMessage) factory             .getBean("springtestmessage"); }


Note

I chose FileSystemXmlApplicationContext for the sake of simplicity in my example. However, ClassPathXmlApplicationContext is generally a better class to use because it searches not only for context definition files in the classpath but also embedded within JAR files.


Before we move to the next section, the following list describes a couple of additional notes about beans:

  • Beans can be created by Spring via the constructor (as you normally would using a new statement) or via static factory methods of another class.

  • Each bean must have a unique id (for example, springtestmessage).

  • Beans can be of two types, Singleton and Prototype (nonsingleton). By default, all beans are singletons, but you can make them prototypes by specifying an attribute such as singleton="false". We will use only singletons for Time Expression because Spring cannot manage the life cycle of a prototype bean after it has been created and handed off to (injected in) the objects that depend on it. Also, by specifying singleton="false" for a given bean definition, you are instructing Spring to create a new instance of the bean every time there is a request for this bean. Last, almost 100% of the time, using singleton beans is sufficient.

  • You can inject values in a setter method or constructor as single objects or as collection elements (for example, List, Set, Map, and Properties).

This is all we will discuss about BeanFactory and ApplicationContext classes in this chapter. After we move to the Spring Web MVC Framework (in the next chapter), we will not have to worry about creating either of these objects manually.

However, you might want to familiarize yourself a bit more about how all this works by reading the Spring Reference Documentation (springframework.org). For example, you might want to better understand constructor argument resolution, dependency checking, autowiring of collaborator beans, programmatically interacting with the BeanFactory, injecting null values, method-based injection, and much more. You will also see additional examples of several of these things in the next chapter and in later chapters in this book.

The spring-beans.xsd (or the older spring-beans.dtd) file provides the XML schema for the Spring Framework's application context file. Looking at one of these files in the Spring's software directories might give you some additional insight into the various elements and properties that can be specified in the application context file.

Property Editors

Spring makes heavy use of the java.beans.PropertyEditor interface by allowing custom property editors to be registered, which convert an object into readable text, and vice versa. For example, in the next chapter, we will use it to convert the hours entered on our Enter Hours web page.



Agile Java Development with Spring, Hibernate and Eclipse
Agile Java Development with Spring, Hibernate and Eclipse
ISBN: 0672328968
EAN: 2147483647
Year: 2006
Pages: 219

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net