毫无疑问,Spring 作为最流行的Java框架之一,能够通过提供诸如依赖注入(dependency injection)和控制反转之类(inversion of control)的功能特性,可以非常轻松地创建实用的企业级Java应用程序。
但是坦白讲,Spring 并不仅仅是一个DI和IOC框架。它通过提供一个有用的抽象层,
进一步简化了许多Java 的API,例如JDBC、JMS、Java Mail等。它消除了Java开发人员在执行SQL语句和处理ResultSets以获得所需的Java对象过程中面临的大部分麻烦。这样一来,使用Spring的JdbcTempalte和其他实用程序类来操作JDBC变得容易许多。
因此,在你学习Spring的时候,你学会不只是如何使用它,同时也对如何用Java编写更好的代码和一般的面向对象编程的一些有益的启示。
在本文中,我将分享一些学习Spring时遇到的最佳实践,主要是通过阅读Craig Walls撰写的经典的《 Spring in Action》一书和我自己对Spring的经验心得。《 Spring in Action》这本书对我的影响特别大,因为作者 Craig 优秀的写作风格和他对Spring中每一个概念的独特的讲解方式。如果你还没有拜读过这本书,我强烈建议你去读——它绝对值得你花时间和金钱去读。
在不浪费读者更多时间的情况下,以下是我学习到的三种最佳实践,分享给大家,同时也建议每个Java程序员都应意识到下面提及的点,并在用Java编码过程中有意识地应用。
1. 编码接口
这是我在阅读《 Head First Design Patterns 》(深入浅出设计模式)时首先学到的一个古老的OOP(Object Oriented Programming)指南。 这种OOP设计原理的主要目的是减少两个类之间的耦合,从而增加灵活性。
Spring严格遵循面向对象的准则,并且暴露很多接口来使用关键类,例如,创建JdbcOperation接口以利用JdbcTemplate等等。 这种做法促进了不同层之间的松散耦合。
另一个不错的例子是一个用于提供缓存Cache接口。所有其他缓存实现类都是实现了此接口,例如 EhCache,ConcurrentMapCache和NoOpCache。如果你的代码是依赖于缓存接口,而不是任何特定的实现,那么你就可以切换缓存提供者,而不会影响你的代码的其他部分。
下面是一个使用Collection 集合框架在Java中编写接口的简单代码示例。
1 import java.util.Arrays;
2 import java.util.List;
3 import java.util.stream.Collectors;
4
5 /**
6 * Program to demonstrate coding for interfaces in Java
7 * @author WINDOWS 8
8 */
9 public class Hello {
10
11 public static void main(String args[]) {
12 // Using interface as variable types
13 List<String> rawMessage = Arrays.asList("one", "two", "three");
14 List<String> allcaps = toCapitalCase(rawMessage);
15 System.out.println(allcaps);
16 }
17
18 /**
19 * Using Interface as type of argument and return type
20 */
21 public static List<String> toCapitalCase(List<String> messages) {
22 return messages.stream()
23 .map(String::toUpperCase)
24 .collect(Collectors.toList());
25 }
26 }
这是一个使用Collection框架为Java中的接口编码的简单代码示例。
2. 优先处理非检查型异常,而不是检查型异常
如果你使用过Spring框架,那么便注意到Spring更倾向于处理非检查型异常,而不是检查型异常,最好的例子就是Spring JDBC。
Spring有一个丰富的异常层次结构来描述在连接数据库和检索数据时可能遇到的不同错误,但是这些错误的根源是DataAccessException,它是非检查型异常。
Spring认为,大多数错误是由于无法在catch块中纠正的原因引起的,因此,它决定将异常捕获给开发人员,而不是像Java那样将其强制插入。这样便促使没有空的catch块,甚至更少的try-catch块,使得代码更精简凝练的。
这也是处理Java中的错误和异常时的最佳实践之一。 如果对该主题感兴趣,那么可以查看我的文章《 10 Java Exception best practice 》,以获得更多建议。
3.模板设计模式的使用
Spring大量使用设计模式中的模板方法来简化事情。这方面的一个很好的例子是JdbcTemplate,它在使用JDBC API时省去了很多麻烦。您只需要定义它需要什么,而Spring负责处理流程的其余部分。
不知你是否知晓,模板模式定义的过程或算法,我们虽不能改变其过程,但是却可以根据实际需要自定义步骤。
例如,在处理JDBC时,可以使用JdbcTemplate执行查询并获取所需的对象。 你只需要提供在每种情况下都不同的SQL,以及用于从一个表中的行映射到对象的映射逻辑。
下面的图很好地解释了模板模式。你可以看到虽然每个人做不同的工作,但是他们都有一些共同的任务,这被一个模板方法很好地捕获了。这个模板方法需要做的就是定义他们的工作,可以通过定义work()抽象方法来实现。
除了JdbcTemplate之外,在Spring的API中还可以发现许多其他使用模板方法模式的例子,例如JmsTemplate和RestTemplate,它们允许使用来自Java应用程序的REST API。
以上就是可以从Spring学到的Java最佳实践。Spring是一个很棒的框架,其作者都是经验丰富的Java开发人员。通过使用Spring以及查看他们的代码、决策以及如何设计API,你可以学到很多东西。Spring是开源的,所以可以下载并查看它们的源代码。
我知道Spring是许多这样的最佳实践的集合,还有很多需要学习,但是我发现这三种实践在Spring中随处可见,这对Spring框架的代码质量产生了巨大的影响。
如果您遇到了从Spring中学到的其他最佳实践,请随时与我们分享。