The author | Tian Hang (spurs)
I believe old Java programmers who have experienced Web project development without using frameworks will feel that today’s programmers are too easy to develop projects, basically only need to care about how to achieve business, general technical problems only need to integrate the framework, eliminating a lot of repetitive trivial configuration work.
After working for a long time, I found that my understanding of Spring was still at the stage of basic use, and I did not have a comprehensive understanding of some of its design evolution, but its design evolution process and ideas are what we can really learn and internalize. Today we’ll talk about the history and capabilities of the Spring framework.
Spring’s past life
Back in 2007, an open source framework based on the Java language was released with a very dynamic and wonderful name called Spring. It is an open source lightweight Java SE (Java Standard Edition) /Java EE (Java Enterprise Edition) development application framework designed to simplify enterprise application development.
In traditional application development, a complete application is made up of a set of cooperating objects. Therefore, in addition to developing business logic, developing an application is mostly concerned with how to make these objects cooperate to complete the required functions, but also with low coupling and high cohesion. Business logic development is inevitable, so having a framework that helps us create objects and manage their dependencies solves a big problem.
Maybe someone said, abstract factory, factory method pattern can help us to create objects, generator pattern can help us to deal with dependencies between objects, can not accomplish these functions? However, this required us to create additional factory classes, generator classes, and we had to manage these classes in addition, which added a lot of burden. If we could create objects and manage dependencies in a configuration way, wouldn’t we have a lot less work to do and a lot more time to do other things? The Spring framework was designed to do this when it first came out.
In addition to helping us manage objects and dependencies, the Spring framework provides many other necessary features and functions, some of which are common.
- Generic logging
- Performance statistics
- Security control
- Exception handling
- Manage the most troublesome database transactions (it provides a simple JDBC access implementation and integration with third party data access frameworks such as Mybatis, JPA, etc.)
- Ability to integrate with various Java EE technologies (such as Java Mail, task scheduling, and so on)
- Provides a Web layer framework of its own, Spring MVC, and can be easily integrated with third-party Web frameworks.
From this point of view, Spring is a super cohesive platform that, in addition to providing its own functionality, provides the ability to glue other technologies and frameworks together, giving us more freedom to choose which technologies to use for development. Both JAVA SE (C/S architecture) applications and JAVA EE (B/S architecture) applications can be developed using this platform.
Spring is no longer a framework, but an ecosystem. SpringBoot’s convenient development realizes zero configuration, and SpringCloud’s whole family provides a very convenient solution. Let’s dig into what Spring has to offer.
It all starts with beans
Speaking of beans, we have to go back to the origin of Java. Back in 1996, Java was still a nascent programming language. It is of interest only because Java applets can be used to develop Web applications as browser components. But developers quickly found the new language also can do more things, and before all the different languages, Java make it possible for modular building complex system (at the time of software industry, although in our business by leaps and bounds, but at the time the development thought is one of the traditional process oriented development, software development efficiency has been faltering. As business complexity increases, development becomes more difficult. OOP was developed in the late 1980s, matured in the 1990s, and most programming languages today are already object-oriented.
In December of that year, Sun released the little-known Javabeans 1.00-A specification. This specification specifies a set of coding strategies that make simple Java objects not only reusable, but also easy to build more complex applications. Although Javabeans were originally designed to reuse application components, they were primarily used to build forms controls, which was the norm in the PC era. But compared to Delphi, VB, and C++, which were then in their heyday, it still seemed too simple to do any “practical” work.
Complex applications typically require transaction, security, and distribution services, but Javabeans don’t provide them directly. So in March 1998, Sun released the EJB 1.0 specification, which extended the design philosophy of Java components to the server side and provided many necessary enterprise-level services, but it was no longer as simple as the early Javabeans. In fact, aside from the name EJB Beans, they have little to do with Javabeans.
Despite the fact that many systems are built on EJB, EJB has never achieved what it was originally intended to do: simplify development. EJB’s declarative programming model does simplify many infrastructure aspects of development, such as transactions and security; On the other hand, EJBs have become extremely complex in terms of deployment and supporting code implementation. Over time, many developers have become disillusioned with EJBs and are looking for a cleaner approach.
Now the concept of Java component development is back on track, with the advent of new programming technologies SUCH as AOP and DI, which provide Javabeans with powerful capabilities previously available only to EJBs. These technologies provide an EJB-like declarative programming model for POJOs without introducing any of the complexities of EJBs. When simple Javabeans do the job, people don’t want to write bulky EJB components.
To be fair, the evolution of EJBs has even promoted a POJO-based programming model. Introducing new ideas, the latest EJB specification is an unprecedented simplification of the previous specification, but for many developers, it all comes too late. By the time the EJB 3 specification was released, other POJO-based development frameworks had become de facto standards, and the Spring framework emerged in this context.
Spring was designed for
Spring is designed to address the complexities of enterprise application development, and it can do a lot of things. But at the end of the day, Spring is underpinned by a few basic ideas, all of which can be traced back to a fundamental mission: to simplify development. This is a serious promise, and many frameworks claim to simplify things in some way. Spring aims to simplify Java development in all its aspects. In this regard, it mainly adopts four strategies:
Pojo-based lightweight and minimally invasive programming; 2. Loose coupling through dependency injection and interface oriented; 3. Declarative programming based on section; Reduce boilerplate code through sections and templates;
The above four strategies are implemented in three main ways:
- For Bean (BOP)
- Dependency Injection (DI)
- Aspect oriented (AOP)
The beginning of BOP programming
Spring is bean-oriented Programming (BOP), and beans are the real heroes in Spring. Beans are what Objects are to OOP in Spring. Without beans there is no reason for Spring to exist. Spring provides the IOC container to manage dependencies between objects through configuration files or annotations.
Inversion of control (emphasis in the interview: the most common implementation is called Dependency Injection (DI) and another, Dependency Lookup (DL), is available in C++, Java, PHP, and Java. There are applications in NET. Inversion of control is also called dependency injection (DI). The basic concept of DI is that you do not create objects, but describe how to create them. Objects and services are not directly connected in the code, but which components require which services are described in the configuration file. The container (IOC container in the Spring framework) is responsible for tying these together.
In a typical IOC scenario, the container creates all the objects and sets the necessary properties to wire them together, determining when methods are invoked.
Basic concepts of dependency injection
Spring design is the core of the org. Springframework. Beans package (core architecture is org. Springframework. Core package), its design goal is to use with JavaBean component. This package is typically not used directly by the user, but is used by the server as an underlying intermediary for most other functions. The next highest level of abstraction is the BeanFactory interface, which is an implementation of the factory design pattern that allows objects to be created and retrieved by name. The BeanFactory can also manage relationships between objects.
At its lowest level, the BeanFactory supports two object models.
Singleton: Provides a globally shared instance object with a specific name that can be retrieved at query time. Singleton is the default and most commonly used object model. Prototype: Ensure that a separate instance object is created for each retrieval. The prototype pattern is used when each user needs his or her own object.
The Bean factory concept is the foundation of Spring as an IOC container. IOC shifts responsibility for handling things from application code to the framework.
AOP programming philosophy
Section-oriented programming, or AOP, is a programming idea that allows programmers to modularize behavior such as logging and transaction management of crosscutting concerns or boundaries of crosscutting responsibilities. AOP’s core construct is facets, which encapsulate behaviors that affect multiple classes into reusable modules.
AOP and IOC are complementary technologies that take a modular approach to solving complex problems in enterprise application development. In a typical object-oriented development approach, logging might be implemented by placing logging statements in all methods and Java classes. In the AOP approach, you can, in turn, modularize logging services and declaratively apply them to components that require logging. The advantage, of course, is that Java classes do not need to know about the existence of the logging service, nor do they need to worry about the associated code. Therefore, application code written with Spring AOP is loosely coupled.
AOP’s functionality is fully integrated into the context of Spring transaction management, logging, and various other features. Common scenarios for AOP programming are:
- Authentication
- Auto Caching
- Error Handling (uniform Error Handling)
- Debugging (Debugging information output)
- Logging
- Transactions.
Spring5 system architecture
In total, Spring has about 20 modules, made up of more than 1,300 different files. These components are integrated in Core Container, AOP (Aspect Oriented Programming), and Device support, and Data access and integration, respectively Access/Integeration), Web, Messaging, Test, 6 modules set. Here is the module structure diagram for Spring 5.
Each set of modules or modules that make up the Spring framework can exist independently or as a combination of one or more modules. The composition and functions of each module are as follows:
Core container
The core container consists of spring-beans, spring-core, spring-Context and Spring-Expression (SpEL) modules.
The Spring-Core and Spring-Beans modules are the core modules of the Spring framework, including Inversion of Control (IOC) and Dependency Injection (DI). The BeanFactory interface, the core interface in the Spring framework, is a concrete implementation of the factory pattern. The BeanFactory uses inversion of control to separate the configuration and dependency specifications of the application from the actual application code. However, BeanFactory does not automatically instantiate beans after they are instantiated. BeanFactory only instantiates and assembs dependencies on beans when they are in use.
The Spring-Context module is built on top of the core module and extends the BeanFactory by adding Bean lifecycle control, framework event system, and resource loading transparency. In addition, the module also provides many enterprise-level support, such as mail access, remote access, task scheduling, etc. ApplicationContext is the core interface of the module, and its superclass is BeanFactory. Unlike BeanFactory, the ApplicationContext container automatically instantiates all singleton beans and assembs them with dependencies, leaving them in a waiting state.
Spring-expression module is an extension module of the Unified Expression Language (EL). It can query and manage running objects, call object methods, and manipulate arrays and collections. Its syntax is similar to traditional EL, but it provides additional functionality, most notably function calls and simple string template functions. The features of the language are designed to meet the needs of Spring products and make it very easy to interact with Spring IOC.
AOP and device support
AOP and device support consists of spring-AOP, Spring-Aspects and Spring-Instrument modules.
Spring-aop is another core module of Spring. It is the main implementation module of AOP. As one of the most influential programming ideas for programmers after OOP, it has greatly expanded people’s thinking about programming. In Spring, it builds on the JVM’s dynamic proxy technology and then designs a series of AOP crosscutting implementations, such as pre-notification, return notification, exception notification, and so on. At the same time, the Pointcut interface matches pointcuts. You can use existing pointcuts to design crosscuts. You can also extend the relevant methods to cut in according to your needs.
The Spring-Aspects module integrates with the AspectJ framework and primarily provides multiple AOP implementations for Spring AOP.
The spring-Instrument module is designed based on java.lang. Instrument in JAVA SE. It should be regarded as a support module of AOP. The programmer implements AOP functionality by modifying the bytecode of a class at run time through proxy classes, thereby changing the functionality of a class.
Data access and integration
Data access and integration consists of spring-JDBC, Spring-TX, spring-ORM, spring-JMS and spring-OXM modules.
The Spring-JDBC module is the main implementation module of the SPRing-provided JDBC abstraction framework to simplify Spring JDBC operations. Mainly provides JDBC template mode, relational database object mode, SimpleJdbc mode, transaction management to simplify JDBC programming, The main implementation classes are JdbcTemplate, SimpleJdbcTemplate and NamedParameterJdbcTemplate.
The Spring-TX module is the Spring JDBC transaction control implementation module. It encapsulates transactions well and can be configured flexibly at any layer through its AOP configuration. In fact, transactions are based on business logic, a complete business should correspond to a method in the business layer, if the business operation fails, the whole transaction will be rolled back. Therefore, transaction control should definitely be at the business level, but the design of the persistence layer should follow one important principle: atomicity of operations, i.e. every method in the persistence layer should be indivisible. Therefore, when using Spring JDBC transaction control, you should be aware of its specificity.
The Spring-ORM module is the ORM framework support module, It mainly integrates Hibernate, Java Persistence API (JPA) and Java Data Objects (JDO) for resource management, Data access Object (DAO) implementation and transaction strategy.
The Spring-OXM module mainly provides an abstraction layer to support OXM (OXM stands for Object-to-XML-Mapping, which is an O/M-mapper that maps Java objects to XML data, Or map XML data to Java objects), for example: JAXB, Castor, XMLBeans, JiBX, XStream, etc.
The Spring-JMS module (Java Messaging Service) can send and receive messages. Since Spring Framework 4.1, it also provides support for the Spring-Messaging module.
Web components
The Web component consists of spring-Web, Spring-WebMVC, Spring-WebSocket and Spring-WebFlux modules.
The Spring-Web module provides the most basic Web support for Spring, mainly on top of the core container. It initializes the IOC container through servlets or listeners, and also includes some Web-related support.
The Spring-WebMVC module is known as a Web-servlet module, which implements the Spring MVC (Model-view-Controller) Web application.
The Spring-WebSocket module is mainly a protocol for communicating with the Web front-end in full duplex.
Spring-webflux is a new non-blocking functional Web framework Reactive that can be used to build asynchronous, non-blocking, event-driven services that scale very well.
The communication message
The Spring-Messaging module is a new module added from Spring4. Its main responsibility is to integrate some basic message delivery applications for the Spring framework.
Integration testing
The Spring-test module mainly provides support for testing, after all, the ability to perform integration tests or other tests without having to publish to your application server or connect to other enterprise facilities is very important for any enterprise.
Integration is compatible with
The spring-Framework-Bom (Bill of Materials) module solves the problem that different spring modules depend on different versions.
Dependencies between modules:
Spring version naming rules
Spring version naming rules are relatively concise and standard, unlike Windows, 98, 2000, XP, Win7, Win8, Win10, chaotic.
The last
There’s a lot to explore about Spring’s design evolution, especially the classic development problems it solves, and it’s worth going back to that environmental perspective to think about what we would do if we were in our shoes. At the same time, there are many design specifications and design pattern practices in Spring source code that we should learn and practice in our daily work coding.
Some people say that Spring is a bit clunky now, but in my opinion, the Spring ecosystem has saved us a lot of work. Designing a common framework that can accommodate different business features requires a lot of consideration. Besides, Spring doesn’t force us to use its integration. Instead, it leaves a lot of options open for developers to decide on their own, which is not easy to do at this point.