简介

Spring 是一个 Java 平台的开源框架,官网:https://spring.io/。它提供了一系列底层容器和基础设施及为 Java Web 应用提供了大量的扩展支持。应该是目前最流行的 Java 后端开发框架,涉及 Java 后端开发的基本上离不开 Spring 了。

核心特性

Spring 的核心就是 IoC(Inversion of Control,控制反转)和 AOP(面向切面编程)。

Ioc(控制反转)

IoC(控制反转)是面向对象中的一种设计思想,用于降低代码间的耦合度。

IoC(控制反转)实现的方式主要有两种:依赖注入(Dependency Injection,简称 DI)和依赖查找(Dependency Lookup)。而依赖注入是一种更好的实现方式,所以平时说到控制反转就想到了依赖注入。我看到有人说控制反转和依赖注入是等价的,但我觉得这两者并非等价。我的理解是控制反转是设计思想,而依赖注入是具体的实现方式。

关于控制反转,谁控制谁?控制什么?反转又是什么?这里直接引用开涛的话:

谁控制谁,控制什么:传统Java SE程序设计,我们直接在对象内部通过new进行创建对象,是程序主动去创建依赖对象;而IoC是有专门一个容器来创建这些对象,即由Ioc容器来控制对象的创建;谁控制谁?当然是IoC 容器控制了对象;控制什么?那就是主要控制了外部资源获取(不只是对象包括比如文件等)。

为何是反转,哪些方面反转了:有反转就有正转,传统应用程序是由我们自己在对象中主动控制去直接获取依赖对象,也就是正转;而反转则是由容器来帮忙创建及注入依赖对象;为何是反转?因为由容器帮我们查找及注入依赖对象,对象只是被动的接受依赖对象,所以是反转;哪些方面反转了?依赖对象的获取被反转了。

来源:https://www.iteye.com/blog/jinnianshilongnian-1413846

IoC,简单理解就是把获取依赖对象的方式交给 IoC 容器来实现,由容器来控制对象的创建、查找及注入依赖对象。

DI(依赖注入),就是 IoC 容器将某个依赖对象注入到组件中。依赖注入的目的是提供组件复用率,并非为软件系统带来更多功能。

更详细的介绍可参考:谈谈对Spring IOC的理解

也可看看 死磕Spring之IoC篇 - 深入了解Spring IoC(面试题) 这篇文章,写得挺好的。

最后总结:控制反转中的『控制』指的是由 IoC 容器来控制对象的创建;『反转』指获取依赖对象的方式反转了。

AOP(面向切面编程)

AOP,面向切面编程,它是一种编程思想,是面向对象编程(OOP)的一种补充。旨在将横切关注点和核心业务进一步分离,以提高程序代码的模块化程度。

这里的『横切关注点』可以理解为与核心业务代码无关的、在多个模块出现的、封装的代码模块(如函数、类、方法等)。

面向切面的程序设计将代码逻辑切分为不同的模块(即关注点(Concern),一段特定的逻辑功能)。几乎所有的编程思想都涉及代码功能的分类,将各个关注点封装成独立的抽象模块(如函数、过程、模块、类以及方法等),后者又可供进一步实现、封装和重写。部分关注点“横切”程序代码中的数个模块,即在多个模块中都有出现,它们即被称作横切关注点(Cross-cutting concerns, Horizontal concerns)。

我们在使用面向对象编程中,当有重复代码出现时,可以将其封装然后复用,但复用的都是核心业务逻辑,并不能复用到一些辅助逻辑,比如日志记录、权限校验、事务管理、性能统计等。我们只能在对象中引用公共行为,这样做不便于维护,AOP 的出现就是弥补 OOP 的这点不足。

如下面这个例子:

public class OrderServiceImpl implements IOrderService {
    @Override
    public void saveOrder(OrderParam param) {
        // 权限校验
        checkPermission();
        // 日志打印
        log.info("订单参数:" + e);
        log.info("性能统计开始");

        // 业务逻辑实现......
        do();

        log.info("性能统计结束");
    }
}

核心业务代码就 do() 方法,但是为了校验权限、记录日志、性能统计,硬是加了一些无关业务的代码,这仅仅是一个类,还有更多的类需要这样做,这就产生了大量的重复代码和繁琐的工作。随着需求的变化,我们需要修改校验权限的方法,又或者不需要记录日志了,那我们是不是得一个一个类去修改?想想这得多恐怖!

实际上,上述的这个问题我们可以使用 AOP 来解决。我们只需声明一个切面,写上切面逻辑:

@Aspect
@Component
@Slf4j
public class OrderAspect {

    /**
     * 定义切入点
     */
    @Pointcut("execution(* com.lanweihong.service.*.*(..))")
    public void doService() {
    }

    @Before("doService()")
    public void doBefore() {
        // 权限校验
        checkPermission();
        log.info("订单参数:" + e);
        log.info("性能统计开始");
    }

    @AfterReturning("doService()")
    public void doAfterReturning() {
        log.info("性能统计结束");
    }
}

无论有多少个方法,我们只需要修改切面逻辑就能让所有业务方法生效。这极大了提供了我们的开发效率,同时减少了系统的重复代码,降低了模块之间的耦合度,有利于未来的可扩展性和可维护性。

关于 Spring AOP 的其他介绍与使用可查看我的另一篇文章:Spring AOP介绍及注解使用

组成模块

Spring 框架大约由 20 个模块组成,这些模块主要有 Core Container(核心容器)、Data Access/Integration(数据访问/集成)、WebAOP(面向切面编程)、AspectsInstrumentationMessaging(消息传递)、Test(测试),如下图所示:

模块组成

Core Container(核心容器)

Spring 的核心容器是其他模块建立的基础,由 spring-corespring-beansspring-contextspring-expression 组成。

spring-core 模块是其他模块的基本组成部分,包括 IOC(控制反转)、DI(依赖注入)特性。

spring-beans 模块提供 BeanFactory ,这是一个工厂模式实现的。

spring-context 模块是基于 Core 和 Beans 模块上提供一个框架式的对象方式,是访问定于和配置的任何对象的媒介。spring-context-support 支持将常见的第三方库集成到 Spring 应用程序上下文中,如缓存(EhCache、Guava)、邮件(JavaMail)、调度(Quartz)和模板引擎(FreeMarker、Velocity)。

spring-expression 模块提供了强大的表达式语言,用于运行时查询和操作对象图。这是 JSP 2.1 规范中指定的统一表达式语言(unified EL)的扩展。该语言支持设置和获取属性值、属性分配、方法调用、访问数组、集合和索引器的内容、逻辑和算数符、命名变量以及从 Spring IOC 容器中按名称检索对象。

Data Access/Integration(数据访问/集成)

由上图可看出,数据访问/集成层由 JDBC、ORM、OXM、JMS和事务组成。

spring-jdbc 模块提供了一个 JDBC 抽象层,它消除了繁琐的 JDBC 编码和数据库厂商特有的错误代码解析。

spring-tx 模块支持特殊接口与所有 POJO 类的编程和声明式事务管理。

spring-orm 模块为流行的对象关系映射 API 提供集成层,包括 JPA和Hibernate。可以将这些 O/R 映射框架与 Spring 提供的其他功能结合使用,比如声明式事务管理。

spring-oxm 模块提供了一个抽象层,支持对象/XML 映射实现,例如 JAXB、Castor、XMLBeans、JiBX 和 XStream。

spring-jms 模块(Java Message Service:Java 消息传递服务)包含用于生成和使用消息的功能。自 Spring Framework 4.1 后,它提供了 spring-messaging 模块的集成。

Web

Web 层由 spring-webspring-webmvcspring-websocketspring-webmvc-portlet 组成。

spring-web 模块提供基本的 Web 集成功能,例如多文件上传功能、使用 Servlet 监听器初始化 IOC 容器及 Web 应用上下文。

spring-webmvc 模块(也称为 Web-Servlet 模块)包含 用于 Web 应用程序的 Spring MVC 和 REST Web Services 实现。

spring-websocket 模块是 Spring Framework 4.0 后新增的,提供了 WebSocket 和 SocketJS 的实现。

spring-webmvc-portlet 模块(也称为 Web-Portlet 模块)提供了 Portlet 环境下的 MVC 实现。

AOP(面向切面编程)和 Instrumentation

spring-aop 模块提供了一个符合 AOP 联盟的面向切面的编程实现,允许你定义方法拦截器和切入点。

spring-aspects 模块提供与 AspectJ 的集成。

spring-instrument 模块提供类检测支持和类加载器的实现以在特定的应用服务器中使用。

Messaging(消息传递)

Spring Framework 4.1 后新增了 spring-messaging 模块,该模块提供了对消息传递体系结构和协议的支持。

Test(测试)

spring-test 模块支持使用 JUnit 或 TestNG 对 Spring 组件进行单元测试和集成测试。它提供了一致的 ApplicationContext 加载和这些上下文的缓存,还提供了可用于单独测试代码的模拟对象。

总结如下:

组成思维导图

参考文献

[1]. Spring框架 - 维基百科,自由的百科全书

[2]. Introduction to the Spring Framework

[3]. Inversion of Control Containers and the Dependency Injection pattern

[4]. IoC 之 2.1 IoC基础 ——跟我学Spring3 - 《亿级流量网站架构核心技术》~ - ITeye博客

[5]. 谈谈对Spring IOC的理解 - 孤傲苍狼 - 博客园

[6]. Spring AOP——Spring 中面向切面编程

文章目录