如何限制不同包下仅DrugOrderManager可访问OrderCancellationService?
这个需求其实是Java里控制服务访问范围的典型场景,咱们可以根据项目的实际情况选择下面几种方案:
方案1:包私有访问修饰符(最简单直接)
核心思路是把OrderCancellationService和DrugOrderManager放到同一个包下,然后去掉OrderCancellationService的public修饰符(默认的包私有访问权限),这样只有同一个包内的类能访问它,外部包的代码根本看不到这个类。
修改后的代码示例:
调整包结构后的DrugOrderManager:
package de.mycompany.order; public class DrugOrderManager { private static final DrugOrderManager INSTANCE = new DrugOrderManager(); private DrugOrderManager() { } public static DrugOrderManager getInstance() { return INSTANCE; } public void cancelOrder() { OrderCancellationService.getInstance().process(); } }
同包下的OrderCancellationService(去掉public):
package de.mycompany.order; // 没有public修饰符,默认是包私有 class OrderCancellationService { private static OrderCancellationService INSTANCE = new OrderCancellationService(); private OrderCancellationService() { } public static OrderCancellationService getInstance() { return INSTANCE; } public void process() { } }
这种方式的好处是实现简单,不需要额外依赖或复杂配置,完全利用Java基础的访问控制机制。
方案2:Java模块系统(适合Java 9+的模块化项目)
如果你的项目已经采用了Java 9及以上的模块系统,可以通过module-info.java精确控制包的访问权限,只允许DrugOrderManager所在的模块访问OrderCancellationService的包,其他模块无法访问。
配置示例:
假设DrugOrderManager在模块mycompany.order.gateway,OrderCancellationService在模块mycompany.order.management:
mycompany.order.management模块的module-info.java:
module mycompany.order.management { // 只把OrderCancellationService所在的包暴露给指定模块 exports de.mycompany.ordermanagement.order to mycompany.order.gateway; }
mycompany.order.gateway模块的module-info.java:
module mycompany.order.gateway { // 依赖管理模块 requires mycompany.order.management; }
这种方式适合大型模块化项目,能在模块层面严格控制访问范围,不会因为包结构调整而失效。
方案3:静态内部类(完全隐藏实现)
如果OrderCancellationService完全不需要独立存在,只服务于DrugOrderManager,可以把它改成DrugOrderManager的私有静态内部类,这样外部代码完全无法访问到这个服务类,彻底实现“仅网关调用”的要求。
修改后的代码示例:
package de.mycompany.jakarta.order; public class DrugOrderManager { private static final DrugOrderManager INSTANCE = new DrugOrderManager(); private DrugOrderManager() { } public static DrugOrderManager getInstance() { return INSTANCE; } public void cancelOrder() { OrderCancellationService.getInstance().process(); } // 私有静态内部类,仅DrugOrderManager能访问 private static class OrderCancellationService { private static OrderCancellationService INSTANCE = new OrderCancellationService(); private OrderCancellationService() { } public static OrderCancellationService getInstance() { return INSTANCE; } public void process() { } } }
这种方式的优点是实现了最高级别的封装,但缺点是OrderCancellationService无法被其他类复用,如果后续需求变化需要扩展调用方,调整起来会比较麻烦。
内容的提问来源于stack exchange,提问作者Hari

