当前位置: 首页 > 编程笔记 >

Spring基础篇之初识DI和AOP

那存
2023-03-14
本文向大家介绍Spring基础篇之初识DI和AOP,包括了Spring基础篇之初识DI和AOP的使用技巧和注意事项,需要的朋友参考一下

前言

  作为从事java开发的码农,Spring的重要性不言而喻,你可能每天都在和Spring框架打交道。Spring恰如其名的,给java应用程序的开发带了春天般的舒爽感觉。Spring,可以说是任何一个java开发者通往技术高阶的必备基础。当然,要学好Spring,尤其是了解Spring的底层原理并不容易,需要花费很多时间和精力来潜心的研习,并在实际的项目中不断的试错和总结,才能形成属于自己的思维理解。博主对Spring最初的认识颇浅,项目中遇到问题依靠度娘大概也能笼而统之的解决。不过呢,接触Spring这么一年多时间里,对其框架体系认知比较杂乱,深层技术依然是雾里看花一般,没有形成自己的认知和理解,这对编程技术的提升是十分不利的。鉴于此,才决定静下心来从头至尾系统的学习Spring框架,并通过博客的形式记录学习点滴,分享技术知识,算是抛砖引玉吧。好了,闲言少叙,咱们开始切入正题——

Spring框架核心介绍

  DI(Dependency Injection),依赖注入,和我们常听说的另一个概念 IOC(控制反转)其实归根结底实现的功能是相同的,只是同样的功能站在不同的角度来阐述罢了。这里博主就不去过多的辨析,度娘上有一大堆解释。我们需要知道的是,什么叫依赖注入,为什么要依赖注入。搞清这两点,我想对Spring的学习在思想上就算是上道了。

  在没用使用Spring的时候——也就是没有依赖注入的时候,java应用程序的类与类之间要实现相互的功能协作是比较费劲的,某个类(A)要实现它的功能如果需要依赖另一个类(B)的协作的话,就需要在A类中主动创建出B类的对象,才能使用B类的方法完成功能(这里看官就不要去纠结静态方法之类的情况了)。这等于是A类需要负责B类对象整个生命周期的管理。在极度简单的情况下,在一个类中new出另一个类的对象似乎并没有什么问题,但是复杂的应用程序类与类的协作关系往往是多边的,我们并不知道一个类功能的实现会依赖多少个另类对象来协作,所以在类中自行创建对象并且管理对象的整个生命周期,会造成代码的高度耦合以及不可想象的复杂度。那么,试想,如果我们能将对象的生命周期交给第三方组件来管理,当某个类需要另外的对象时第三方组件就直接创建出来交给它,这样,类就可以只专注于自己功能的实现,而不用去管理其他类对象的生命周期,这样类的功能就单纯了很多。是的,你一定已经明白了,Spring(容器)就是这个第三方组件。我们只需要告诉Spring(容器)有哪些对象需要管理就行了,不用去关心Spring框架是如何创建对象的。这样,当某个类A需要类B对象时,如果类B已经声明交给了Sping容器管理,那么在程序运行到类A需要类B时,Spring容器就通过依赖注入的方式,将类B对象注入到类A中协助完成业务功能。通过第三方组件的依赖注入,对象无需再自行的创建和管理类与类之间的依赖关系了。对象的创建依赖注入的方式也有多种,譬如接口注入,构造方法注入,setter方法注入等等。说到这里,你对依赖注入应该有比较直白的认知了。至于为什么要依赖注入,上文已经说得很明白了,就是为了减少代码中组件之间的耦合度,我们还是先通过简单示例来直观感受下依赖注入比自己管理对象的好处吧——

public class Man implements Human {
  private QQCar car;
  public Man() {
    this.car = new QQCar();
  }
  @Override
  public void xiabibi() {
  }
  public void driveCar(){
    car.drive();
  }
}

    接口Car暂有两个实现:奔驰车和QQ车,在以上Man类和QQCar类高度耦合的代码中,老司机通过构造器只创建了QQ车对象,所以只能开QQ车,那么老司机想开奔驰怎么办呢,你让他重新创建奔驰车的对象吗?这样高度耦合的代码似乎是毫无办法的,那么,我们通过注入对象的方式对上述代码做一番改进:

public class Man implements Human {
  private Car car;
  public Man(Car car) {
    this.car = car;
  }
  @Override
  public void xiabibi() {
  }

  public void driveCar() {
    car.drive();
  }
}

 以上代码根据多态特性,通过构造器接口注入的方式屏蔽掉了具体的对象实现,这样,老司机就能想开什么车就开什么车了。这就是依赖注入带来的好处。

  AOP(Aspect Oriented Programming),面向切面编程。日常开发中,我们在完成某个业务功能的时候,写了一堆代码,到最后代码优化的时候发现,真正完成业务的代码可能就那么两句,而其余都是与该部分业务相关度不大,仅仅是为了实现某种技术的代码,是完全可以抽离出去的,于是很自然的,我们会将其抽取成一个工具类,这样凡是用到的地方只需调用一下工具方法就ok了。我们再站高一点看,各个业务模块的功能组件中除了完成相关的业务功能外,都有涉及日志、事务、安全控制等额外的操作等。这些并不是模块的核心功能,却又不可或缺。如果将这些额外功能添加进代码,业务系统每个组件都来一套又显得太过重复,而且让业务代码显得混乱,不够纯粹。这个时候,你问上帝,可不可以让你的业务代码只专注于业务的实现,不去管什么日志、事务等不相干的东西?喔,上帝说没问题,于是就有了AOP。如果说依赖注入的目的是让相互协作的组件保持一种较为松散的耦合状态的话,AOP则是将遍布应用各处的功能分离出来形成可重用的组件。通俗点说,日志、事务等都是可以重用的组件,我们完全可以将分散于业务代码各处的日志、事务、安全等功能代码抽离出成为一个单独的工具组件,在Spring的配置中将其进行声明为一个功能切面,再告诉Spring你想在哪些地方、什么时机使用(切入)这些可重用组件就行了。这就是我对面向切面的简单释义。该篇只是引子,所以博主就只是简单阐述一下概念,不做具体的代码、配置实现,在会在后续的博文中将陆续奉上,欢迎拍砖。

 类似资料:
  • 在我们第一次开始写程序的时候,都是以 Hello World 开始的。或者: printf("hello,world"); 又或许: alert('hello,world'); 过去的十几年里,试过用二十几种不同的语言,每个都是以 hello,world 作为开头。在一些特定的软件,如 Nginx,则是 It Works。 这是一个很长的故事,这个程序最早出现于1972年,由贝尔实验室成员布莱恩·

  • 然而,这样的设计有几个重要的缺陷。第一,我们要么在使用之前就列出一个原语的详细清单,要么继续扩展API来引入新的原语。第二,这种设计不能为那些使用这个服务的应用提供足够的灵活性以实现最适合它们的原语。 数据的确实经常暗含了关于一个znode重要的信息。在master-worker的例子中,举个例子,缺少master节点(以下znode均译为节点)意味着当前没有master被选举出来。图2-1包含了

  • 本文向大家介绍Python基础知识点 初识Python.md,包括了Python基础知识点 初识Python.md的使用技巧和注意事项,需要的朋友参考一下 Python简介 Python的历史 1989年圣诞节:Guido von Rossum开始写Python语言的编译器。 1991年2月:第一个Python编译器(同时也是解释器)诞生,它是用C语言实现的(后面又出现了Java和C#实现的版本J

  • 本文向大家介绍C#基础知识之FileStream,包括了C#基础知识之FileStream的使用技巧和注意事项,需要的朋友参考一下 一、FileStream的基础知识   属性:            CanRead 判断当前流是否支持读取,返回bool值,True表示可以读取            CanWrite 判断当前流是否支持写入,返回bool值,True表示可以写入   方法:    

  • 本文向大家介绍Ruby基础知识之类,包括了Ruby基础知识之类的使用技巧和注意事项,需要的朋友参考一下 创建类: class后跟类名,其中类名的首字母必须要大写。实例化时,通过new方法实例化。在c#中有构造器,构造器与类同名。在ruby中,构造器为initialize方法。当通过new方法实例化一个类对象后,会自动调用initialize方法,把new中的参数传递给initialize方法进行初

  • Socket 通常也称作"套接字",是支持 TCP/IP 协议的网络通信应用的基本操作单元,可以用来实现网间不同虚拟机或不同计算机之间的通信。使用TCP/IP协议的应用程序通过在客户端和服务器各自创建一个 Socket ,然后通过操作各自的 Socket 就可以完成客户端和服务器的连接以及数据传输的任务了。 Socket 的本质是编程接口( API ),是对 TCP/IP 的封装。使开发者不需要面