java-间接引用

引用的必要

一个文件实现一个复杂功能的时代已经过去了,甚至一个工程实现一个项目都逐渐被淘汰。

限于层级的划分、项目的管理、功能的扩展等因素,在程序的设计之初,就有了引用的概念。

使用既定的方式,去使用已经完成的功能或者对象。

部门间的流转、模块间的导入都是如此,仅仅关注于自身的逻辑管理,而其他部分只关注接口。

诸多的编程语言中,基本的共同点,就是包、模块的引入。

Go语言中,方法间存在两种引用:值传递和引用传递。

一个大对象,占据内存为S,如果是值传递,经过n个操作方法,内存占用为(n+1)×S(n +1) \times S

但是,如果使用地址传递,也就是地址引用,消耗内存为S+4×nS + 4 \times n

不论是功能还是其他方面,引用都是大有用处,也无处不在。

奇妙的对象

面向对象的模式的优缺点不用再讨论,我也没能力置喙,只是说说它和引用的奇妙关联。

面向对象的封装模式,更提高了内聚,但是引出一个本质问题:多层引用

我们通过模块引入一个类,实例化类之后通过对象引用方法。

尤其重要的是,我们更依赖于对象的引用,这就把引用的本质,或者面向对象的本质给显露出来。

普遍的引用,通过方法的传递,或者模块的导入即可完成,但是面向对象中间还夹杂了实例化这个步骤。

总结一下,面向对象的几个繁琐点

  • 个体依赖性

模块可以直接引用、方法可以直接调用,但是面向对象中依赖的并不是直接的外部接口,而是依赖的具体对象。

即使是同一个类,由于参数的不同,相同的方法之间的差异性也非常巨大,不存直接引用这种说法。

  • 引入复杂性

由于前述的一点,当涉及多个对象组合的功能的时候,如何引入这些依赖的对象。

加上其他模块对于基础对象的相同的引入,不可能由某一个特定的使用类来具体的实例化。

同时,不管由构造器还是外部方法进行设置,都显得十分笨拙。


或者还有其他原因,但都大同小异,那就是:面向对象带来了引入的动态性质。

之前的引入,都是静态的,但是基于对象而非类的依赖,尤其是对象的封装特性,我们不可能做到统一的引入。

势必,要有那么一个东西,支持、简化、统一我们的对象的引用。

注入(DI)

模块和方法都是静态的,对其接口即可,对象确实动态的,必须指定个体。

而且由于可能的多方面的引用,无法交给任何一个调用类来进行实例化管理,必须存在一个中心的容器,去维护这些基础的素材。

最后,让对象,和其他语言中的模块一样,成为一种静态的,可无歧义的直接进行引用。


每种语言,支持的都是基础的静态引用,而java中的办法,或者说spring的方案是:使用一个对象容器,来进行维护管理

然后通过注入这种方式,来模仿导入的过程。也即是,你说你需要,我一个个给你们填充。

看看一个文件中高达十几个的类引用,想到一个个的实例化的恐惧,想到几十个类之间的交叉引用,庆幸。


几十个的get/set,谁都会对代码丧失兴趣。

控制(IOC)

然后,接踵而来的更重要的问题,管理的对象哪里来。

如果说借助容器,我们自己去挨个注册,自己去实例化,不说多么无味和重复,只是,有必要么。

通过反射,或者其他什么办法,让容器自主的能够去创建、管理对象。

减少失误,提高开发进度,尤其死板的严格的管控条例,获得更准确的服务保障,这就是IOC的极大优势。

切面(AOP)

不得不说,基于对象引用的繁杂操作让人厌烦,但是,其所带来的操作空间的确巨大。

对于一个基础的功能,如果我们想要稍微修饰一下,就会显得十分鸡肋

  • 方法包装

可以写方法进行包装,但是却可能时常更换,浪费人力,切效用不大

  • 操作包裹

操作时候去修饰,冲淡逻辑的紧密性,分散精力,冗余垃圾代码


不论采取什么方式都显得鸡肋----但是,java中这种问题不复存在。

moduleplatformprocesswraperloadcallwrappermoduleplatformprocess

如上,鸡肋让我们不论从模块还是程序的角度,都无法保证纯净。

modulejvmcontainerprocessloadinstance and wrappercallmodulejvmcontainerprocess

多出来的中间过程,让我们可以尽情的去定制所需要的即将引用的对象及其方法。

在每个阶段都能够保证自身的纯净、逻辑的聚合。

其中的从加载到容器的阶段,正是切面(定制)的活动空间。

由于jvm是基于class的中间语言的平台,从javaclass的步骤,也是这一步的领域。

因此,切面在于已经加载对象的重新定制,还有javaassist等基于字节码的包装功能。

不论是加载即包装,还是引用即包装,都是对象引用所提供的定制化的操作空间。

fileclassobjectcontainerprocessloadinstancemanagercallfileclassobjectcontainerprocess

忽略具体细节,把class字节码文件等同于java的内容,就可以统一理解。

注意:class的直接定制,由于不存在更多的联结特性,效能优于基于对象的包装方案。

操作的空间

如果非直接的流程,在中间的传输过程中,就可能存在更多可能的操作,提供更多的使用空间。

ribbon的负载均衡,正是由于注册中心的非直接调用,才得以实现。

微服务中的小模块,管理和调用,正如java中的对象引用的管理,容器中心也就变成了服务中心。

简单的引用,其本质,天差地别。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章