这个话题,估计大多数人没兴趣.因为觉得这个太容易了,直接调用不就完了.
但是呢,以下分析是我当年刚参工作两三年时看到日志调用时候的一点疑问,当时懒惰,没整理出答案.现在整理一下,以备日后查看.
1 这个问题很我觉得有意思是对于写一些中间件或者小框架的人还是很有帮助的.
问题如下,对于项目中没有清理过maven的依赖(毕竟有中间依赖,确实会导致同时出现)的情况下,同时出现如下两个
<dependency> <groupId>commons-logging</groupId> <artifactId>commons-logging</artifactId> <version>1.2</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>jcl-over-slf4j</artifactId> <version>1.7.25</version> </dependency>
这个时候,classpath上是有两个
org.apache.commons.logging.LogFactory和两个
org.apache.commons.logging.Log
我的问题来了:这在运行中用的是哪一个org.apache.commons.logging.LogFactory
真实的答案其实是,不管classloader先加载到哪一个org.apache.commons.logging.LogFactory,最终都没不会有问题.
细节我不说了,主要是如果先加载到
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.2</version>
</dependency>
源码中都这样干,核心代码就下面两句话我单独拿出来了
final InputStream is = getResourceAsStream(contextClassLoader, SERVICE_ID);
protected static final String SERVICE_ID = "META-INF/services/org.apache.commons.logging.LogFactory";
其实好多给人写框架时如果想留下扩展的时候都是这样干的,这也就是值得稍微了解一下的
SPI机制