依赖的类型

    在现实生活中,我们的要做某件事情或者从事某项活动之时,我们无法独立行为必须依靠外界某事或者某物的帮助才能实施,这就是依赖的定义。依赖是有上下文的不是说随时随地任何事都需要,比如骨折的时候需要拐杖,但他坐着却不需要任何协助。这不让人联想到Java依赖的管理,肯定没有一个简单的通用的分类概括所有的依赖关系。在Java的世界里,我们也应该针对上下文环境对依赖区别对待,下面我参考Maven对依赖SCOPE的定义分析解释一下:

编译(Compile)

    到底为何需要依赖?这个问题最简直最直接的回答是你的项目源代码至少需要第三方的工具来完成编译啊!没有适当的编译,你的源代码就是一段文本不能称作算法。这时定义依赖的作用就是告诉编译过程用什么方式去操作(编译)这段源代码。这不仅包括你构建工具的依赖(Maven Ant) , 还包含那些源代码所引用的依赖。
    这些依赖中一些只是在编译的阶段需要的,还有一些在随后的过程依然有用。就我的印象中,大多数编译的依赖会延续到代码执行阶段,但是对构建工具、编译器和注解处理器的依赖就到此为止了。
    这就产生一个有趣的现象,编译时的依赖环境要比执行的时候繁杂得多。比如说你创建一个注解来处理java.util.ServiceLoader 在meta下面的文件配置,这种情况下编译阶段就需要javax.lang.model和javac compiler,而执行时java.util就足够了。

连接(Linkage)

    在编译完成后,系统运行之前,连接开始装载整个应用并处理所有外部导入的引用。所以说这个阶段的所有依赖应该跟编译阶段是一致的。但是Maven里的可选依赖就是一个例外:某些依赖只应用于某些功能,而且当没有该功能时也不存在该依赖。理想状况下,一个功能可能被划分为一个子模块,该子模块是一个只有核心功能的项目,由于当你要使用这个子工程的功能的时候,你会需要它的全部,所以这个子工程只含有非可选性依赖。
   这种情况下,连接依赖就是编译依赖的子集。

运行(Runtime)

        毫无疑问连接是系统执行的第一个动作。但是连接不是系统执行唯一动作,并且执行时环境配置的要求会跟连接时大不一样。举个例子,我建立一个数据库的应用,你连接的时候肯定是不需要数据库的Class文件,但你跑代码的时候它确必须随时就位。 这种情况下,运行依赖就是连接依赖的超集。
        还可以以前面ServiceLoader为例:作为一个API 它不需要任何实现,但是运行时我们必须加入实现保证功能正常。连接的时候不需要实现作为依赖,执行时实现作为依赖加入,这体现了模块化的设计思路。

测试(Test)

    测试的依赖相对独立,也比较好理解。用TDD方式开发代码,测试代码跟源代码紧密关联。貌似,测试代码应该和源码共享同一套依赖,但是实际情况呢?这里需要解释一下。通常我们需要依赖第三方(Easy mock)来创建一些测试对象,但是这些依赖不会成为发布的一部分。这意味着谁要给代码加测试都需要一套不同于正常运行时依赖的测试依赖。另外,我们一般不会把test作为单独的module而依赖源码和测试的工具,因为把测试类和产品代码放在同一个包中,但位于不同的源代码树,这种可以容易获取包访问权限。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值