[Open Source and Project Combat: Open Source Combat] 84 | Open Source Combat IV (Part 1): Analysis of the classic design ideas or principles contained in the Spring framework

In the Java world, the Spring framework has almost become a must-have framework for project development. As such an excellent and popular open source project, it is one of the preferred materials for our source code reading. Whether it is design ideas or code implementation, there are many places worth learning. Next, we will talk about the design ideas, principles and patterns contained in the Spring framework in detail. Because the content is relatively large, I will explain it in three parts.

  • In the first part, we explain the classic design ideas or principles contained in the Spring framework.
  • In the second part, we explain two design patterns used in the Spring framework to support extensions.
  • In the third part, we summarize and list more than a dozen other design patterns used in the Spring framework.

Today, we will talk about the first part: some design ideas or principles contained in the Spring framework, including: convention is greater than configuration, low intrusion and loose coupling, modular and lightweight, etc. These design ideas are very general, after mastering, we can use them for reference in the development of other frameworks.
Not much to say, let's officially start today's study!

A brief introduction to the Spring framework

Considering that you may not be familiar with Spring, I will briefly introduce it here. The Spring framework we often refer to refers to the Spring Framework basic framework. Spring Framework is the cornerstone of the entire Spring ecosystem (also known as the Spring family bucket). In addition to the Spring Framework, there are more frameworks developed based on the Spring Framework in the Spring family bucket that integrate more functions, such as Spring Boot and Spring Cloud.

In the Spring family bucket, Spring Framework is the most basic and bottom part. It provides the most basic and core IOC and AOP functions. Of course, it contains more than that, and there are many other functions such as transaction management (Transactions), MVC framework (Spring MVC) and so on. The following table is what I found from the Spring official website. You can have a rough impression of the Spring Framework’s function introduction.

insert image description here
In the Spring Framework, Spring MVC has a high appearance rate and is often used alone. It is an MVC framework that supports Web development, and provides a series of functions related to Web development, such as URL routing, Session management, and template engine.
Spring Boot is developed based on Spring Framework. It is more focused on microservices development. The reason why the word "Boot" is included in the name is related to its original design intention. The original intention of Spring Boot is to quickly start a project, and use it to quickly realize the development, deployment and operation of a project. All the functions supported by Spring Boot are designed around this original intention, such as: integrating many third-party development packages, simplifying configuration (for example, specification is better than configuration), integrating embedded Web containers (for example, Tomcat, Jetty), etc.

For a single microservice development, it is enough to use Spring Boot, but if you want to build an entire microservice cluster, you need to use Spring Cloud. Spring Cloud is mainly responsible for the service governance of microservice clusters, including many independent functional components, such as Spring Cloud Sleuth call chain tracking, Spring Cloud Config configuration center, etc.

Looking at the role of the framework from Spring

If you have used some frameworks for development, you should be able to feel the advantages of using framework development. Here I will summarize a little bit. The benefits of using the framework are: decoupling business and non-business development, allowing programmers to focus on business development; hiding complex implementation details, reducing development difficulty, and reducing code bugs; realizing code reuse and saving development time; standardized and standardized project development, Reduce learning and maintenance costs and more. In fact, if I had to sum it up in one sentence, it would be simplifying development!
For the summary just now, let's explain it in detail.

Compared with pure CRUD business code development, non-business code development is more difficult. Therefore, developing some non-business general codes as frameworks and reusing them in projects not only saves development time, but also reduces the difficulty of project development. In addition, the framework has been verified many times by multiple projects. Compared with redeveloping each project, the code bugs will be relatively less. Moreover, different projects use the same framework. For developers, the learning cost of switching from one project to another will be greatly reduced.

Next, let's take common Web project development as an example.
By introducing the Spring MVC development framework into the project to develop a web application, we only need to create three classes of Controller, Service, and Repository, fill in the corresponding business code, and then do some simple configuration to inform the framework of Controller, Service, and Repository The calling relationship between classes, and the remaining non-business-related work, such as object creation, assembly, management, request parsing, encapsulation, and mapping between URL and Controller, are all done by the framework.
Not only that, if we directly introduce the more powerful Spring Boot, the work of deploying the application to the web container will be saved. Spring Boot embeds web containers such as Tomcat and Jetty. After writing the code, we can complete the deployment and operation of the project with a single command.

Design Ideas Contained in the Spring Framework

In the Google Guava source code explanation, we talked about some common development ideas for developing general-purpose functional modules, such as product awareness, service awareness, code quality awareness, and don’t repeat early wheels. Today, let's analyze some classic design ideas (or development techniques) behind the Spring framework. These design ideas are not unique to Spring, they are relatively general, and can be used for reference in the design and development of many general function modules. This is also the value of our learning Spring source code.

1. Convention over configuration

In projects developed with Spring, the configuration is often complicated and cumbersome. For example, if we use Spring MVC to develop Web applications, we need to configure each Controller class and the URL corresponding to the interface in the Controller class.
How to simplify the configuration? Generally speaking, there are two methods, one is based on annotations, and the other is based on conventions. Both configuration methods are used in Spring. Spring has done a great job in minimizing configuration, and there are many things we can learn from.

Based on the annotation configuration method, we use the specified annotation on the specified class to replace the centralized XML configuration. For example, we use the @RequestMapping annotation to mark the corresponding URL on the Controller class or interface; use the @Transaction annotation to indicate support for transactions, etc.
The convention-based configuration method is also often called "convention over configuration" or "convention over configuration". Reduce configuration through agreed code structure or naming. To put it bluntly, it is to provide the default value of the configuration, and the default value is preferred. Programmers only need to set those configurations that deviate from the convention.

For example, in Spring JPA (a set of JPA application framework encapsulated based on the ORM framework and JPA specification), we agree that the class name is the same as the table name by default, the attribute name is the same as the table field name by default, and the String type corresponds to the The varchar type, the long type correspond to the bigint type in the database, and so on.
Based on the agreement just now, the Order class defined in the code corresponds to the "order" table in the database. Only when we deviate from this agreement, for example, the table in the database is named "order_info" instead of "order", we need to explicitly configure the mapping relationship between the class and the table (Order class -> order_info table).

In fact, convention is better than configuration, which well embodies the "28 rule". In normal project development, 80% of the configurations can use the default configuration, and only 20% of the configurations must be explicitly set by the user. Therefore, configuring based on conventions saves us a lot of time in writing configurations without sacrificing configuration flexibility, saves a lot of mindless pure manual labor, and improves development efficiency. In addition, the development based on the same agreement also reduces the learning cost and maintenance cost of the project.

2. Low intrusion, loose coupling

How intrusive a framework is is an important indicator of how good a framework is. The so-called low intrusion means that the framework code is rarely coupled in the business code. Low intrusion means that when we want to replace a framework, there will be very few changes to the original business code. On the contrary, if a framework is highly intrusive and the code is highly intrusive into the business code, the cost of replacing it with another framework will be very high, or even almost impossible. This is also a very important reason why some old projects that have been maintained for a long time use relatively old frameworks and technologies and cannot be updated.
In fact, low intrusion is a very important design idea followed by the Spring framework.
The IOC container provided by Spring can incorporate them into Spring's management only through configuration without requiring Beans to inherit any parent class or implement any interface. If we change an IOC container, we only need to reconfigure it, and the original Bean does not need any modification.

In addition, the AOP function provided by Spring also reflects the low intrusion feature. In the project, for non-business functions, such as request logs, data collection points, security verification, transactions, etc., we don't need to invade them into business code. Because once intruded, these codes will be scattered in various business codes, and the cost of deletion and modification will become very high. However, based on the development model of AOP, the non-business code is concentrated in the aspect, and the cost of deletion and modification becomes very low.

3. Modular and lightweight

We know that more than ten years ago, EJB was the mainstream development framework for Java enterprise applications. However, it is very bloated, complex, intrusive, highly coupled, and the development, maintenance, and learning costs are not low. Therefore, in order to replace the bulky EJB, Rod Johnson developed a set of open source Interface21 framework, which provides the most basic IOC functions. In fact, the Interface21 framework is the predecessor of the Spring framework.

However, with continuous development, Spring is now not just a small framework that only includes IOC functions. It has obviously grown into a "platform" or "ecology" that includes various functions. Even so, it didn't repeat the same mistakes and become a bulky and unwieldy framework like EJB. How did Spring do it?

This is due to Spring's modular design idea. Let's look at a picture first, as shown below, it is a module and layered introduction diagram of Spring Framework.

insert image description hereWe can see from the figure that Spring does a very good job in layering and modularization. Each module is only responsible for a relatively independent function. The relationship between modules is only the dependency of the upper layer on the lower layer, while there is almost no dependence and coupling between the same layer and the lower layer to the upper layer. In addition, in projects that rely on Spring, developers can selectively introduce certain modules, and will not be forced to introduce the entire Spring framework just because they need a small function. Therefore, although the Spring Framework contains many modules, there are already more than two dozen, each module is very lightweight and can be used alone. Because of this, until now, the Spring framework can still be called a lightweight development framework.

4. Re-encapsulation and re-abstraction

Spring not only provides various common functional modules for Java project development, but also further encapsulates and abstracts mainstream middleware and system access libraries on the market, providing a higher level and more unified access interface .
For example, Spring provides the spring-data-redis module, which further encapsulates Redis Java development libraries (such as Jedis and Lettuce), adapts Spring's access methods, and makes programming access to Redis easier.

And Spring Cache, which we will talk about in the next class, is actually a kind of re-encapsulation and re-abstraction. It defines a unified and abstract Cache access interface, which does not depend on specific Cache implementations (Redis, Guava Cache, Caffeine, etc.). In the project, we access Cache based on the abstract and unified interface provided by Spring. In this way, we can switch between different caches without modifying the code.

In addition, remember the JdbcTemplate we talked about in the template mode before? In fact, it is also a further encapsulation and abstraction of JDBC in order to further simplify database programming. Not only that, Spring also further encapsulates JDBC exceptions. Encapsulated database exceptions inherit from the DataAccessException runtime exception. This type of exception does not need to be caught mandatory during development, thus reducing unnecessary exception catch and processing. In addition, the database exception encapsulated by Spring also shields the details of different database exceptions (for example, different databases define different error codes for the same error report), making exception handling easier.

key review

Well, that's all for today's content. Let's summarize and review together, what you need to focus on.
With the help of the Spring framework, we summarize the role of the framework: decoupling business and non-business development, allowing programmers to focus on business development; hiding complex implementation details, reducing development difficulty, and reducing code bugs; realizing code reuse and saving development time; Standardize and standardize project development, reduce learning and maintenance costs, etc. In fact, if I had to sum it up in one sentence, it would be simplifying development!
In addition, we also focused on some classic design ideas behind Sping, mainly including: convention over configuration, low intrusion, loose coupling, modularization, lightweight, repackaging, and abstraction. These design ideas are relatively general, and we can learn from them in the development of other frameworks.

class disscussion

  • "Convention is better than configuration" is reflected in many development scenarios, such as Maven and Gradle construction tools, which agree on a set of default project directory structures. In addition, what other ideas can you think of that embody this design idea? Are you developing a scene?
  • Referring to the design idea of ​​Spring, analyze the design idea behind a framework, class library, and functional components that you are familiar with.

Guess you like

Origin blog.csdn.net/qq_32907491/article/details/131365645