如何在Javadoc中为模块生成仅展示SPI的Uses/Provides服务章节(不暴露未导出包的实现类)?
如何在Javadoc中为模块生成仅展示SPI的Uses/Provides服务章节(不暴露未导出包的实现类)?
哈哈,我前阵子刚踩过这个坑!其实你就差一个精准的Javadoc参数,先给你直接上解决方案,再慢慢拆解原因和验证步骤。
问题出在哪?
你观察得特别到位:标准库的模块文档(比如java.base)既能正常显示Services章节,清晰列出@uses/@provides的服务信息,又能牢牢守住封装边界——不会把未导出的服务实现类暴露出来。但你自己试的时候,要么Services章节直接不生成,要么用--show-module-contents all把不该漏的实现类也抖出来了。
这是因为Javadoc的默认策略是“最小化展示”,不会主动输出模块的服务相关内容;而--show-module-contents all是“最大化展示”,会把模块里所有内容(包括未导出的包、内部实现类)都扒出来,显然不是我们要的效果。标准库用的是一个中间选项,专门针对服务内容的。
正确的解决方法
你只需要给Javadoc加上这个参数:
--show-module-contents services
这个参数的作用就是:专门让Javadoc生成模块的Services章节,只展示通过@uses和@provides声明的服务信息,同时严格隐藏未导出的实现类和其他模块内部细节,完全复刻标准库模块文档的表现。
用你的示例验证一下
把你的javadoc-args.txt更新成下面这样:
--module-source-path demo=src --module demo -Xdoclint:all -d out/docs --show-module-contents services
重新运行Javadoc生成文档后,你会看到:
- 模块总结页面里Services章节正常出现了,清晰展示了你用
@provides java.lang.System.LoggerFinder声明的服务 - 未导出的
com.example.DummyLoggerFinder实现类完全不会被暴露,和java.base等标准库模块的文档效果一模一样
几个补充说明
- 服务类型的位置不影响:不管你用的SPI是来自当前模块,还是像
System.LoggerFinder这样来自java.base等标准模块,只要你在模块注释里正确用了@uses/@provides标签,配合这个参数就能生成正确的服务章节。 - 无需导出提供者的包:你之前的判断是对的,服务提供者的包完全不需要导出,Javadoc只会展示SPI的接口类型,不会泄露具体实现类,完美符合模块化的封装原则。
- 为什么默认不生成?:Javadoc默认是“保守展示”,只对外暴露模块明确导出的内容,服务信息属于模块的“可选元信息”,所以必须通过参数明确开启展示。
内容来源于stack exchange
相关产品推荐
相关产品推荐

