spring6源码阅读(二):spring-core解析
构建
spring-core的源码结构和其他模块都不一样,他是有针对于不同jdk版本分别优化的,查看构建文件即可发现,他引入了multiReleaseJar插件,对源码文件实现了分别目录进行打包.
构建时在项目根目录下使用命令./gradlew :spring-core:jar
gradlew是gradle的wrapper机制,推荐阅读 https://www.cnblogs.com/wenzhuo4657/articles/19095336
踩坑记录:
1,代理问题,默认使用的maven中央仓库,我是使用tun模式解决了这个问题,构建时间为1m30s。
这里暂时不去深究为什么要对jdk21、24进行特殊处理,即便谈论起原因也大概是由于jdk的变化,例如jdk8使用反射不需要导入即可使用,但使用jdk17却由于模块化的特性需要导入。
log模块源码阅读
LogDelegateFactory
LogDelegateFactory是对org.apache.commons.logging.LogFactory的扩展,证据是该日志工厂使用的Log、LogFactory都是comons包下的,且注意,LogFactory.getLog是一个静态方法,所以无需导入即可使用。
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
public static Log getHiddenLog(String category) {
return LogFactory.getLog("_" + category);
}
另一方面LogDelegateFactory也就是spring框架的加料是方法getCompositeLog,他来自core包下的另一个类org.springframework.core.log.CompositeLog
public static Log getCompositeLog(Log primaryLogger, Log secondaryLogger, Log... tertiaryLoggers) {
List<Log> loggers = new ArrayList<>(2 + tertiaryLoggers.length);
loggers.add(primaryLogger);
loggers.add(secondaryLogger);
Collections.addAll(loggers, tertiaryLoggers);
return new CompositeLog(loggers);
}
从类内容来看,他传入了一个类似于日志树的结构,如果a不存在就使用b,不过无论如何具体的实现还是交给了CompositeLog。
CompositeLog
根据LogDelegateFactory的使用方式,我首先查看了构造器结构,发现该类仅仅存在这一个有参构造器,且对应属性仅仅存在一个调用。
private Log getLogger(Predicate<Log> predicate) {
for (Log logger : this.loggers) {
if (predicate.test(logger)) {
return logger;
}
}
return NO_OP_LOG;
}
根据观察,特征有两个
1,for循环遍历本质上走的Iterator遍历器模式,而list对于该模式的实现是顺序遍历,
2,条件匹配predicate.test是一个函数式接口,用于计算匹配的logger,但是需注意该方法是private级别的,只能由同类中的其他方法调用,从入参来看,是用于匹配info、erro等日志级别的谓词。
此时产生了问题,如果CompositeLog实现的效果仅仅是如果只是没有a就使用b,或者日志级别的判定,那么他似乎和log记录器本身自带的日志树记录没有区别,转而查看getCompositeLog方法的描述解决了我的疑问。
创建一个复合记录器,该记录器委托给主记录器,或者如果未启用主记录器的日志记录,则回退到辅助记录器上。
这可用于从逻辑上应该与一些更高级别的包一起记录的较低级别包的回退日志记录,但两者碰巧没有共享合适的父包(例如,Web 和较低级别的 http 和编解码器包的日志记录)。对于这种情况,主(基于类)记录器可以使用共享回退记录器包装。
形参:
primaryLogger – 首先尝试的主要记录仪
secondaryLogger – 二级记录仪
tertiaryLoggers – 可选的可替代记录仪
返回值:
相关类别的合成记录器
重点在于两者碰巧没有共享合适的父包,也就是说该记录器脱离的日志树的记录模式,但实现了相似的效果。
关于测试
org.springframework.core.log.CompositeLogTests的测试使用了Mockito 。
详情可见:XXXXX
遗留
关于getCompositeLog在spring项目中的使用,查看调用可以发现它成为了另外两个日志记录器的轮子,HttpLogging和SimpLogging,这二者都属于spring-messaging包。