可选依赖项

探讨了在软件开发中如何优雅地处理库的可选依赖项,包括自动检测和显式配置两种方法,以及它们各自的优缺点。

有时您正在编写的库可能具有可选的依赖项。 例如“如果apache http客户端在类路径上,请使用它;否则,请使用它。 否则–退回到HttpURLConnection”。

为什么要这么做? 由于各种原因–在分发库时,您可能不想强加较大的依赖范围。 另一方面,更高级的库可能会带来性能上的好处,因此任何需要这些的人都可以包括它。 或者,您可能希望允许轻松插入某些功能的实现,例如json序列化。 您的库不在乎是Jackson,gson还是本机android json序列化–因此您可以使用所有这些库提供实现,然后选择找到依赖项的实现。

实现此目的的一种方法是显式指定/传递要使用的库。 当库/框架的用户实例化其主类时,他们可以传递boolean useApacheClient=true或枚举值JsonSerializer.JACKSON 。 这不是一个坏选择,因为它迫使用户了解他们正在使用的依赖项(并且是事实上的依赖项注入)

spring等使用的另一个选项是动态检查类路径上是否存在依赖项。 例如

private static final boolean apacheClientPresent = isApacheHttpClientPresent();
private static boolean isApacheHttpClientPresent() {
  try {
    Class.forName("org.apache.http.client.HttpClient");
    logger.info("Apache HTTP detected, using it for HTTP communication.);
    return true;
  } catch (ClassNotFoundException ex) {
    logger.info("Apache HTTP client not found, using HttpURLConnection.");
    return false;
  }
}

然后,每当您需要发出HTTP请求时(其中ApacheHttpClient和HttpURLConnectionClient是您自己的HttpClient接口的自定义实现):

HttpClient client = null;
if (apacheClientPresent) {
   client = new ApacheHttpClient();
} else {
   client = new HttpURLConnectionClient();
}

请注意,使用“ isXPresent”布尔值保护所有可能尝试从依赖项加载类的代码非常重要。 否则,类加载异常可能会发生。 例如在Spring,他们将Jackson依赖项包装在MappingJackson2HttpMessageConverter

if (jackson2Present) {
    this.messageConverters.add(new MappingJackson2HttpMessageConverter());
}

这样,如果Jackson不存在,则不会实例化该类,也根本不会尝试加载Jackson类。

究竟是偏爱自动检测还是需要显式配置要使用的基本依赖项,这是一个难题。 因为自动检测可能使您的库用户不知道该机制,并且当他们添加用于其他目的的依赖项时,它可能会被您的库选择并且行为可能会更改(尽管应该这样做,但始终存在微小差异) 。 您当然应该记录下来,甚至记录消息(如上所述),但这可能不足以避免(不愉快的)意外情况。 因此,我无法回答何时使用哪种方法,应视具体情况决定。

这种方法也适用于内部依赖项–您的核心模块可能会寻找一个更具体的模块来使用它,否则会回退到默认值。 例如,您使用System.nano()提供了“经过时间”的默认实现,但是使用Android时,您最好依靠SystemClock –因此,您可能希望检测是否存在经过时间的android实现。 这看起来像逻辑耦合,因此在这种情况下,最好还是使用显式方法。

总的来说,这是使用可选依赖项的一种很好的技术,它具有基本的后备功能。 或没有回退的许多可能选项之一。 很高兴知道您可以做到,并将其包含在问题的可能解决方案的“工具包”中。 但是您不应该总是在显式(依赖注入)选项上使用它。

翻译自: https://www.javacodegeeks.com/2015/06/optional-dependencies.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值