为什么要使用Spring?(Spring的设计目标是什么?Spring解决了什么样的问题,让我们如此推崇?)很多书籍对于Spring的普遍解释是用来替代更加重量级的企业级Java技术,尤其是EJB,Spring为开发者提供了一个一站式的轻量级应用开发框架(平台)。Spring是技术发展的产物,我们年轻的一代学者没有经历过三层模型,没有经历过EJB,或许真的很难对Spring这样的技术有切身的体会,充其量只能停留在一些表面的认识之上。在写这篇文章的时候,我也只是对为何使用Spring有一个模糊的认识而已。知史可以明鉴,建议大家可以阅读这篇文章:https://blog.csdn.net/bntX2jSQfEHy7/article/details/78898595,描述了Web发展的简史。

由于我对EJB并没有特别的了解,也不敢妄加评判,下面只谈Spring带给我们的好处。总所周知,IOC和AOP是Spring所依赖的根本。

IOC容器

控制反转(Inverse of Control,IOC)有时也被称为依赖注入,是一种降低对象之间耦合关系的设计思想。

耦合会有什么问题呢?耦合具有两面性。一方面,紧密耦合的代码难以测试,难以复用,难以理解。如果对象之间通过显式调用进行交互会导致调用者与被调用者存在着非常紧密的联系,其中一方的改动还将会导致程序出现很大的改动。并且典型的表现出“打地鼠”式的bug特性(修复一个bug,将会出现一个或者更多的bug)。另一方面,一定程度的耦合有时必须的,完全没有耦合的代码什么也做不了。为了完成有实际意义的功能,不同的类必须以适当的方式进行交互。总而言之,耦合是必须的,但是应该被谨慎管理。

如果使用Spring作为应用开发平台,通过使用Spring的IOC容器,可以对这些耦合关系(对Java代码而言)实现一个文本化,外部化的工作,也就是说,通过一个或几个XML文件,我们就可以方便的对应用对象的耦合关系进行浏览,修改和维护,这样,可以在很大程度上简化应用开发。同时,通过IOC容器实现的依赖反转,把依赖关系的管理从Java对象中解放出来,交给了IOC容器来完成,从而完成了对象之间的关系解耦;原来对象—对象的关系,转化为对象—IOC容器—对象的关系,通过这种关系,更体现出IOC容器对应用的平台作用。

如图所示,假设为一家卖茶的商店设计一套管理系统,这家商店开业时,只卖绿茶。随着规模的扩大,未来可能需要销售例如红茶,等其他的茶类品种。传统的实现方式会针对茶抽象化一个基类,绿茶类只需要继承自该基类即可。

当需要使用绿茶时,只需要执行以下代码:AbstractTea t = new GreenTea();这种方法是可以满足当前的设计要求的。如果店家准备更改为销售红茶,那么需要实现一个BlackTea的类,所有用到AbstractTea t = new GreenTea();的地方修改为AbstractTea t = new BlackTea();这种创建对象实例的方法,往往导致程序的改动量非常大。

有什么办法可以增强系统的可扩展性呢?——设计模式,此时可以使用设计模式中的工厂模式来把创建对象的行为包装起来。实现方法如下所示。

通过以上的方法,可以把创建对象的过程委托给TeaFactory来完成,在需要使用Tea对象时,只需要调用Factory类的getTea方法即可,具体创建对象的逻辑在TeaFactory中来实现,那么当商家需要把绿茶替换成红茶的时候,系统中只需要改动TeaFactory中创建对象的逻辑即可,采用了工厂模式后,只需要在一个地方做改动就可以满足要求。

虽然说采用工厂设计模式之后增强了系统的可扩展性,但是从本质上来讲,工厂模式不过是把程序中会变动的逻辑移动到工厂类中,当系统中的类较多的时候,在系统扩展时需要经常改动工厂类中的代码。采用IOC设计思想后,程序会有更好的可扩展性。如下图所示:

Spring容器将会根据配置文件来创建调用者对象(Sale),同时把被调用的对象(AbstractTea的子类)的实例化对象通过构造函数或者Set()方法的形式注入到调用者对象中。

所以到底有什么好处呢?还是要修改配置文件,修改配置文件和修改代码有什么区别呢?代码的可读性也会因为配置文件变的比较差?看了这么多,真的是道理我都懂?实际意义的好处,我还是没有明白。希望有理解的同学,可以留言告诉我。

另外还有一点,IOC容器中默认创建的对象是单例的,就像是一个对象的池子一样,类似于线程池,数据库的连接池,可以复用的对象。

在面向接口编程,因此我们在每次使用一些工具类的时候,或者一些需要实例化才可以调用的对象,这就会存在大量的实例化对象,并且他们的生命周期可能就是从方法的调用开始到方法的调用结束为止,无形之中加大了GC回收的压力。

了解设计模式的可能会想到使用单例模式的方式来解决这个问题,以此来避免大量重复的创建对象,但是我们还要考虑到众多的这种对象的创建都需要改成单例模式的话,是一个耗时耗力的操作。对于这个系统来说,如果都把这种面向接口的对象实现类转换为单例模式的方式的话,大概也要写十几个或者上百个这种单例模式代码,而对于一个单例模式的写法来说,往往是模板式的代码。

可以看出,这种方式有两个问题:

(1)业务代码与单例模式的模板代码放在一个类里,耦合性较高;

(2)大量重复的单例模式的模板代码;

从上述可以看出,使用的单例模式虽然从性能上有所提高,但是却加重了我们的开发成本。因此只会小规模的使用,例如我们操作JDBC的Utils对象等

我们即需要一个单例的对象来避免系统中大量重复对象的创建和销毁,又不想因为使用单利模式造成大量重复无用的模板代码和代码的耦合!Spring的IOC容器便是做到这一点。

具体而言,IOC主要有以下两个方面的优点:

  1. 通过IOC容器,开发人员不需要关注对象如何被创建的,同时增加新类也非常的方便,只需要修改配置文件即可实现对象的热插拔。
  2. IOC容器可以通过配置文件来确定需要注入的实例化对象,因此非常便于进行单元测试。

尽管如此,IOC容器也有自身的缺点,具体表现如下:

  1. 对象时通过反射机制实例化出来的,因此会对系统性能有一定的影响。
  2. 创建对象的流程变得比较复杂。

AOP

面向切面编程(Aspect-Oriented Programming,AOP)是面对对象开发的一种补充,它允许开发人员在不改变原来模型的基础上动态地修改模型以满足新的需求。

为什么要使用AOP?https://blog.csdn.net/bntX2jSQfEHy7/article/details/78898592

这篇博客的内容,我认为是一个很好的表述。

很有人会有一个疑问,AOP面向切面的编程和,把这些重复性的代码抽取出来,调用公共方法有什么区别?调用这些重复性代码会导致,我们的业务代码已经被这些非核心的代码所混淆,并且占据了大量的空间!使得代码的可读性变差。

设计模式中的动态代理,可以实现一个简单的AOP功能,那么Spring的AOP和JDK的动态代理设计模式又有什么区别呢?我们的代理目标对象必须实现一个接口,要是一个接口的实现类,这是因为再生成Proxy对象的时候这个方法需要一个目标对象的接口:

显然,有些特殊的场景使用JDK动态代理技术的话,已经不能够满足我们的场景了。Spring在这里使用CGLib动态代理的方式实现了我们的这种诉求。CGLib采用底层的字节码技术,可以为一个类创建子类,在子类中采用方法拦截的技术拦截所有父类方法的调用并顺势的织入横切逻辑。

参考资料:

  1. 《Java程序员面试笔试宝典》,何昊,薛鹏,叶向阳著,2018年4月第1版;
  2. https://blog.csdn.net/bntX2jSQfEHy7/article/details/78898595
  3. https://blog.csdn.net/bntX2jSQfEHy7/article/details/78898592

为什么要使用Spring?相关推荐

  1. spring boot项目 中止运行 最常用的几种方法

    spring boot项目 中止运行 最常用的几种方法: 1. 调用接口,停止应用上下文 @RestController public class ShutdownController impleme ...

  2. html+spring boot简单的ajax数据传输实现

    本篇讲解在前后端不分离情况下的html+spring boot的项目数据传输实现 首先,后台我写了三个接口 package com.demo.ajax.controller;import com.de ...

  3. Spring Boot整合Spring Data JPA操作数据

    一. Sping Data JPA 简介 Spring Data JPA 是 Spring 基于 ORM 框架.JPA 规范的基础上封装的一套 JPA 应用框架,底层使用了 Hibernate 的 J ...

  4. Spring AOP + Redis解决重复提交的问题

    Spring AOP + Redis解决重复提交的问题 用户在点击操作的时候,可能会连续点击多次,虽然前端可以通过设置按钮的disable的属性来控制按钮不可连续点击,但是如果别人拿到请求进行模拟,依 ...

  5. Spring cloud 微服务docker容器化最佳实践

    Spring cloud 是当下最炙手可热的微服务套件,我们将介绍如何整合Docker容器达到高效快捷的构建发布 采用了dockerfile-maven-plugin插件发布镜像到远程docker主机 ...

  6. ssh(Struts+spring+Hibernate)三大框架整合-简述

    ssh(Struts+spring+Hibernate)三大框架配合使用来开发项目,是目前javaee最流行的开发方式,必须掌握: 注意: 为了稳健起见,每加入一个框架,我们就需要测试一下,必须通过才 ...

  7. Strutsw2与Spring整合流程-简述

    1.      新建WEB工程: 2.      导入struts2开发包,和资源配置文件 ① globalMessages.properties ② struts.properties 3.     ...

  8. spring Bean自动装配

    spring Bean自动装配 自动装配是使用spring满足bean依赖的一种方式. spring会在应用上下文中为某个bean寻找其依赖的bean. spring自动装配需要从两个角度来实现,或者 ...

  9. spring IOC创建对象方式

    spring IOC创建对象方式 通过无参构造来创建 验证方法: 创建实体类: public class User {private String name;public User() {System ...

  10. 第一个spring程序

    第一个spring程序: 第一步:导入jar包. 新建maven项目: <dependency><groupId>org.springframework</groupId ...

最新文章

  1. web前端培训:CSS中单行文本溢出显示省略号的方法
  2. Create PDB with Sample schemas in 12C
  3. html粘贴excel内容,如何用JS解析剪切板里的excel内容
  4. 评审专家:基金本子“瘦”点好
  5. 计算机组成原理中的直接映像,计算机组成原理cache存储器的直接映像与变换.doc...
  6. 四种依恋类型_“我值得被爱吗?”| 如何在亲密关系中培养安全型依恋
  7. Springmvc+mybaits 分页处理+ajax翻页
  8. centos一键安装包无法创建vhost
  9. LINUX SHELL为awt指定分隔符
  10. 计算机二级java难吗_计算机二级上机-计算机二级难吗?二级高级语言:分笔试和上机考试笔试90分钟, 爱问知识人...
  11. 2020.10.30文献1:《滇中引水工程香炉山隧洞地应力特征及其活动构造响应》
  12. not a valid identifier
  13. 最快的扫雷记录,初级只需要0.49秒,一眨眼就结束的操作!
  14. 码分复用:为什么可以通过收到的码片序列与站的序列做内积的值判断每个站是否发送数据及数据值
  15. 数据分析 # 深入分析近三年以来各大城市发展情况
  16. php 模拟百度蜘蛛
  17. 被讨厌的勇气:人际关系论
  18. 与幼儿园小朋友一起过感恩节心得
  19. html5调用手电筒,HTML5的模拟手电筒照明效果
  20. 解决\xEF\xBB\xBF问题

热门文章

  1. 聆听机器人小冰发声有感
  2. Java 里氏代换原则
  3. 计算九宫格解锁的解法和
  4. 相对论【4】一般相对论的普通结果与闵可夫斯基四维空间简单介绍
  5. m序列信号发生器--基于线性移位反馈寄存器LFSR
  6. 重学设计模式(三、设计模式-工厂模式)
  7. 一篇文章搞懂FastDfs(全是干货,建议收藏)
  8. 计算机学校学什么专业,读职高学校学什么专业好 这些最 有出路
  9. 玲珑杯 1160 - 康娜与玲珑杯
  10. n阶乘的递归与非递归的实现