The Spring Framework is an open source application framework that aims to make J2EE development simpler. Spring, unlike single-tier frameworks such as Struts or Hibernate, aims to structure entire applications in a consistent and productive manner by combining the best single-tier frameworks to form a coherent architecture.
Since the widespread adoption of J2EE applications in 1999/2000, J2EE has not been an unqualified success in the real world. While it has brought a welcome standardization to core middle-tier concepts such as transaction management, many, if not most, J2EE applications are overly complex, require excessive effort to develop, and perform poorly. Spring is applicable in a wide variety of environments, not just server-side J2EE applications. However, the original motivation for Spring was the J2EE environment, and Spring provides many useful services for J2EE applications.
Specific causes of complexity and other issues in J2EE applications have been identified through experience. (Of course, J2EE is not the only platform with these issues!) In particular:
J2EE applications typically contain a great deal of "plumbing" code. Numerous code reviews reveal a high proportion of useless code: JNDI lookup code, Transfer Objects, try/catch blocks to acquire and release JDBC resources... The writing and maintenance of such plumbing code is a significant drain on resources that should be devoted to the application's business domain.
Inappropriately, numerous J2EE applications employ a distributed object model. This is one of the primary contributors to excessive code and code duplication. In many cases, it is also conceptually flawed; internally distributed applications are typically more complex and less performant than co-located applications. Clearly, if your business requirements necessitate a distributed architecture, you must implement one and accept the trade-offs it entails (and Spring offers features to help in such scenarios). However, you shouldn't do so unless you have a compelling reason.
EJB's component model is overly complicated. EJB was conceived as a means of reducing complexity when implementing business logic in J2EE applications, but it has not achieved this goal in practice.
EJB is overemployed. EJB was designed primarily for transactional applications that are internally distributed. Even though nearly all nontrivial applications are transactional, distribution should not be built into the basic component model. Many "J2EE design patterns" are not design patterns at all, but rather workarounds for technological constraints. The excessive use of distribution and complex APIs, such as EJB, have spawned numerous questionable design patterns; it is essential to examine these patterns critically and seek out simpler, more efficient approaches.
It is challenging to unit test J2EE applications. Before the agile movement took off, the J2EE APIs and, in particular, the EJB component model were defined. Consequently, their design does not account for unit testing simplicity. It is surprisingly difficult to test EJB and many other J2EE APIs outside of an application server due to their APIs and implicit contracts. Nonetheless, unit testing outside of an application server is essential for achieving high test coverage and reproducing a variety of failure scenarios, such as database connectivity loss. It is also crucial to ensure that tests can be executed quickly during the development or maintenance process, thereby minimizing the amount of unproductive time spent waiting for redeployment.
Certain J2EE technologies have failed miserably. Entity beans have proven to be a major hindrance to productivity and object orientation due to their stifling constraints.
The traditional response to these issues has been to wait for tool support to catch up with the J2EE specifications, so that developers do not have to contend with the aforementioned complexity. However, this has failed substantially. Tools based on code generation approaches have failed to deliver the desired benefits and have exhibited a number of issues of their own. Using this method, you may generate all of these verbose JNDI lookups, Transfer Objects, and try-catch blocks.
Experience has demonstrated that frameworks are superior to tool-enabled code generation. A good framework is typically significantly more flexible at runtime than generated code; it should be possible to configure the behavior of a single piece of framework code, as opposed to modifying numerous generated classes. In many cases, code generation also presents difficulties for round-tripping. A well-designed framework can also provide a consistent abstraction, whereas code generation is typically just a short-cut that fails to hide underlying complexities throughout the project's lifecycle. During maintenance and troubleshooting, complexities frequently re-emerge in a detrimental way.
A framework-based strategy acknowledges that the application developer's perspective is missing from the J2EE puzzle. Much of what J2EE provides, such as JNDI, is simply too low-level to be part of a programmer's daily routine. In actuality, the J2EE specifications and APIs are far more successful if viewed from the perspective that they do not so much offer the developer a programming model as they do provide a solid foundation upon which that model should rest. Good frameworks provide this missing component and provide application developers with a simple, productive abstraction without compromising the platform's core functionality.
It is not desirable to use J2EE "out of the box." Numerous J2EE APIs and services are complicated to employ. J2EE does an excellent job of standardizing low-level infrastructure, resolving issues like how Java code can access transaction management without having to deal with the specifics of XA transactions. However, J2EE does not provide a view for application code that is readily usable. This is the responsibility of an application framework such as Spring.
Recognizing the importance of frameworks to the success of J2EE projects, numerous developers and organizations have attempted to create their own frameworks, with varying degrees of success. In a minority of instances, the frameworks achieved their intended objectives and significantly reduced expenses and increased productivity. In most cases, however, the cost of developing and maintaining a framework itself became an issue, and framework design flaws manifested. Since the core problems are generic, it is preferable to utilize a single, widely-used (and tested) framework as opposed to developing one in-house. No matter how large an organization is, it will be impossible to match the level of experience available for a product utilized by numerous businesses. It is possible to contribute new features and enhancements that can be adopted if the framework is open source, which is an added benefit. (Of course, it is possible to contribute suggestions to commercial products, but it is typically more difficult to influence successful commercial products, and without the source code, it is challenging to make equally useful contributions.) Thus, generic frameworks such as Struts and Hibernate have supplanted in-house frameworks in specific areas.
The Spring Framework evolved from the experience of using J2EE without frameworks or with a combination of in-house frameworks. However, unlike Struts, Hibernate, and the vast majority of other frameworks, Spring provides services that can be utilized throughout an entire application, not just on a single architectural tier. Spring aims to alleviate a significant portion of the pain caused by the problems in the preceding list by simplifying the programming model, as opposed to hiding complexity behind a complex layer of tools.
Spring enables you to enjoy the principal advantages of J2EE while minimizing the complexity of application code.
Providing enterprise services to Plain Old Java Objects is the essence of Spring (POJOs). This is especially advantageous in a J2EE environment, but application code delivered as POJOs is naturally reusable across a wide range of runtime environments.