Without a doubt, the Spring Framework is one of the most popular Java frameworks, making it easy to create real enterprise-class Java applications by providing features such as dependency injection and inversion of control. However, Spring is more than just a DI and IOC framework. It simplifies many Java apis, such as JDBC, JMS, Java Mail, and so on, by providing a useful abstraction layer. It is much easier to use JDBC using Spring’s JdbcTempalte and other utility classes. They remove most of the friction faced by Java developers associated with developing SQL statements and working with ResultSets to get the Java objects they want.
Therefore, when learning the Spring framework, it is important not only to learn how to use it, but also to learn how to write better code in Java and object-oriented programming. In this article, you’ll share some of the best practices you’ve encountered while learning Spring
1. Interface code
This is the old OOP guide I First learned reading the Head First Design Pattern. The main goal of this OOP design principle is to reduce coupling between two classes, thereby increasing flexibility.
Spring strictly follows this object-oriented discipline and often exposes an interface to use key classes, such as creating the JdbcOperation interface to take advantage of the JdbcTemplate. This practice promotes loose coupling between the different layers.
Another good example is the Cache interface, which provides caching. All other cache implementations such as EhCache, ConcurrentMapCache and NoOpCache implement this interface.
If your code relies on the Cache interface and not on any particular implementation, you can switch the Cache provider without affecting the rest of your code.
Here is a simple code example for writing an interface in Java using the Collection framework. If you look closely, in this example I use an interface rather than an implementation to declare variables, parameters, and return method types in Java.
import java.util.Arrays; import java.util.List; import java.util.stream.Collectors; / * *
- Program to demonstrate coding for interfaces in Java
- @author WINDOWS 8
/ public class Hello { public static void main(String args[]) { // Using interface as variable types List rawMessage = Arrays.asList(“one”, “two”, “three”); List allcaps = toCapitalCase(rawMessage); System.out.println(allcaps); } / *
- Using Interface as type of argument and return type */ public static List toCapitalCase(List messages) { return messages.stream() .map(String::toUpperCase) .collect(Collectors.toList()); }}
This coding style is flexible and easier to change in the future.
- Checked exceptions and unchecked exceptions
If you’ve worked with the Spring Framework, you’ve noticed that Spring prefers unchecked exceptions to checked exceptions, the best example being Spring JDBC.
Spring has a rich exception hierarchy that describes the different errors that can occur when connecting and retrieving data from the database, but the root cause of these errors is the DataAccessException, which is unchecked.
Spring believes that most are caused by an inability to correct errors in a catch block, so it decides to catch developer exceptions rather than enforce them as Java does. The result is cleaner code, no empty catch blocks, and fewer try-catch blocks. This is also one of the best practices when dealing with errors and exceptions in Java.
Spring makes extensive use of the Template method design pattern to simplify things. A good example is the JdbcTemplate, which eliminates a lot of trouble when using the JDBC API. You just define what you need, and Spring takes care of the rest of the process.
If you don’t know that a template design pattern defines a process or algorithm, you can’t change the process, but you can tailor the steps to your needs.
For example, when working with JDBC, you can use the JdbcTemplate to execute a query and get the desired object. You just need to provide SQL that is different in each case and the mapping logic to map rows from tables to objects.
This is a nice diagram that nicely illustrates the template design pattern. You can see that everyone has some common tasks, but they do different jobs and are nicely captured by the Template method. All they need to define is their work, which they do by defining work() as an abstract method.
These are some of the Java best practices you can learn from the Spring Framework, and anyway, if you’ve come across any other best practices you’ve learned from the Spring Framework, please share them with us in the comments.