Spring基础篇——DI/IOC和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你想在哪些地方、什么时机使用(切入)这些可重用组件就行了。这就是我对面向切面的简单释义。该篇只是引子,所以博主就只是简单阐述一下概念,不做具体的代码、配置实现,在会在后续的博文中将陆续奉上,欢迎拍砖。

  2017年最后一天了,想想这一年,除了年龄之外,技术、能力都成长的太慢太慢,博文更新太懒惰,很久憋不出点东西了,不善总结、学习,这对技术人员来说是致命的缺点。新的一年,当以此为戒,严格律己,每周至少应有一篇博文总结,以此为誓!

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏编程

C语言怎么学习?以C语言模拟登录为例,学C语言该当如此方可成

好了不用看了,看直了也不会有妹子,看题了: C语言编写代码实现,模拟用户登录------看着是不是很简单?,是不是很轻松?,是不是就有这样的代码? (小编随便百...

3939
来自专栏JAVA技术zhai

你和阿里资深架构师之间,差的不仅仅是年龄(进阶必看)

9399
来自专栏Java技术栈

分享18道Java基础面试笔试题(面试实拍)

上图来自Java技术栈微信群里的群友分享,看起来比较基础,但不一定人人都答得上来。 图片比较模糊,小编把题目进行了文字化。 1.你最常上的两个技术站和最常使用的...

47911
来自专栏Albert陈凯

2018-08-05 没有测试用例的代码,根本不应该跑在服务器上

在实际测试中,一个单元可以小到一个方法,也可以大到包含多个类。从定义上讲,单元测试和集成测试是有严格的区分的,但是在实际开发中它们可能并没有那么严格的界限。如果...

2155
来自专栏竹清助手

现代化PHP开发

PHP 正在重生。作为一门专注WEB开发的语言,它不断吸取其他语言的优点,如命名空间,闭包,性状,操作码缓存等特性,PSR 规范和Composer 包管理以及...

2102
来自专栏圣杰的专栏

DDD理论学习系列(6)-- 实体

1.引言 实体对应的英语单词为Entity。提到实体,你可能立马就想到了代码中定义的实体类。在使用一些ORM框架时,比如Entity Framework,实体作...

2668
来自专栏极客生活

真正好用的python库

这个库是我安装完python环境后第一个安装的库,装上这个库再开始写代码才有底气,作者 Kenneth Reitz 是公认python领域代码写的最好的两个人之...

1243
来自专栏微信公众号:Java团长

不可多得的后端架构师技术图谱!内附参考资料!

由于知识点众多,特整理在GitHub上,微信外链限制,无法在文本中直接加上超链接,有需要的欢迎Start/Fork,地址如下:

1472
来自专栏tkokof 的技术,小趣及杂念

小话游戏脚本(一)

( 题记:近来在网上学习到一个新的观点(应该是来自刘未鹏的BLOG :) ):书写是为了更好的学习,这与之前脑子里传道授业解惑的观点颇为迥异,品一品又颇以为然...

961
来自专栏xdecode

后端架构师技术图谱

转自: GitHub/architect-awesome , 大体结构如下(更新时间: 2018-06-22)

1.3K6

扫码关注云+社区

领取腾讯云代金券