In this chapter, we’ll see how Spring works and review its working principles. We’ll take a detailed look at bean definitions, accessing bean instances, and various bean scopes available in Spring Framework. The chapter also goes into detail about the Application Context lifecycle, with deep dives into the various phases of the lifecycle so that you understand the crux of Spring. Finally, because Dependency Injection is a very important concept in Spring, reducing code maintenance as well as increasing developer productivity, we provide a comprehensive discussion of this subject.
How Spring Works
The Spring container is at the core of Spring Framework. It creates the objects, wires them together, configures them, and manages their complete lifecycle from start (creation) to end (destruction). It uses dependency injection (DI) to manage the components that make up an enterprise application. Each object in the Spring container is called a Spring bean.
The Spring container gets its instructions by reading configuration metadata provided to it and, based on this, it decides what objects to instantiate, configure, and assemble. The configuration metadata can be provided to the container either by XML, Java annotations, or Java code. Weak-application POJO classes combined with the provided metadata instructions added to the Spring Container become powerful components in the enterprise application. Spring achieves all this by not locking down the application to any JEE-specific application servers. Figure 3-1 provides a high-level view of how Spring actually works in lay terms.
Figure 3-1. How Spring works
A Typical Application Requirement
A typical enterprise application consists of many components working together to achieve a business-problem solution. (In our sample application, various modules, such as Customer and Shipment, interact at various stages in an application to realize a business case. Implementing some changes in business dynamics will be cumbersome, however. (With Spring, you have a choice to swap the implementation with mere configurations.) As illustrated in Figure 3-2, each component might or might not interact with another, and as a whole, the enterprise application becomes monolithic in nature, with no way to separate the various components from the enterprise application if there is a change in business dynamics. It also becomes very hard to swap a component with a new implementation, which is a vital requirement in modern business dynamics and is an integral factor when architecting any enterprise application. Spring Framework tries to address these issues in an enterprise application in an easy way, without overhead, and it also reduces maintenance nightmares.
Figure 3-2. Various components in an application work together to actualize a business application.
The main flaws in a typical enterprise application can be summarized as:
- Parts (components) in an enterprise application find it difficult to search and integrate with other parts of the same application.
- A part becomes obsolete because of changing business dynamics of an enterprise application, and it becomes hard to swap or change. This introduces maintenance nightmares and diminishes application agility.
Figure 3-3. A typical interaction between components in our sample application
As shown in Figure 3-3, components interact with one another in an enterprise application in a tightly coupled way, and any change in one component in the assembly point can adversely affect the other component and its behavior. As already mentioned, it also becomes very hard to swap one component with a similar or more sophisticated component, because of business changes/challenges. In the model shown in Figure 3-3, using Spring, at various stages of application, development components can be swapped according to your business needs. For example, if persisting logic changes—for example, moving away from conventional JDBC to Hibernate—you can easily swap the CustomerRepository with a new implementation based on Hibernate and replace it using the application configuration file of Spring container.
In a typical application development cycle, testing cannot be overlooked or ignored. Unit testing with the actual infrastructure might not be the right solution, however, for the infrastructure aspect as well as for the time aspect. In this case, using Spring Framework, each component in the application can be swapped without any code changes to take in a new component implementation that doesn’t have dependency on the actual infrastructure but that does have dependency on a memory database, which is faster and more reliable for unit testing by developers. That is, using Spring, you can write a new implementation of any component, and the application can use these sample implementations by mere Spring configurations for doing the system testing. An easy and convenient way of testing is to use mocks. Spring out-of-box supports unit testing with JUnit and TestNG. Spring provides a separate set of classes to help you unit test your Spring classes. In Chapter 7, we cover testing of Spring applications in detail.
It’s a general conception that over a period of time, with growing complexity and size of the projects, JEE applications becomes more complex and unmanageable. Some of the reasons sttributed for this can be summarized as below:
- JEE applications tend to contain excessive amounts of “plumbing” code which are unnecessary and unmanageable creating complexity and cluttering of code.
- The EJB component model is generally considered to be unduly complex.
- Compared to unit testing capability provided by other fraemworks available in the market, JEE applications are hard to unit test.
Spring to the Rescue
Spring works on the core principle of Inversion of Control (IoC). Using IoC, it tries to address the common issues that any enterprise application faces in the real world. It does this by taking the burden off the shoulders of the developers and allowing easy configurations of various components in an enterprise application. Developers always program to the interface, and Spring out-of-box gives support to creating and autowiring various instances needed by objects in a typical enterprise application.
Spring enables you to enjoy the key benefits of J2EE while minimizing the complexity encountered by application code. The essence of Spring is that it provides enterprise services to Plain Old Java Objects (POJOs). This is particularly valuable in a Java EE environment, but application code delivered as POJOs is naturally reusable in a variety of runtime environments.
Spring allows assembly of an application by using various components. These components have no trouble finding each other, and they can be easily swapped according to the business requirements. The components can be in POJOs and deployed in the Spring container, which in turn manages these objects, which in Spring Framework are called beans.
Page Visitors: 1380