一、动态绑定和静态绑定
- 动态绑定:在运行时才能确定加载哪个对象,往往通过配置文件的方式来加载。类似如下代码
String factoryClass = props.getProperty("org.apache.commons.logging.LogFactory");
Class logFactoryClass = classLoader.loadClass(factoryClass);
logFactoryClass.newInstance();
- 静态绑定:编译的时候就确定了某个对象,简单点说就是你开发的时候直接使用了某个对象。类似如下代码
import org.slf4j.impl.StaticLoggerBinder;
public class Test3 {
public static void main(String[] args) {
new StaticLoggerBinder();
}
}
假如StaticLoggerBinder在另一个包B,然后你打包了Test3为A,然后把A用在另一个项目C。此时你必须引入B才能正常使用,这种A对B的依赖就是静态绑定。
- 总结:动态绑定具体使用哪个对象是不确定的,只要实现了org.apache.commons.logging.LogFactory接口就行,他可能是com.test.A.class或者com.dd.aa.B.class 等等。静态绑定则已经确定了必须是org.slf4j.impl.StaticLoggerBinder,其他的对象都不可以。
二、slf4j-log4j2的初始化流程
Logger logger = LoggerFactory.getLogger(getClass());
初始化由LoggerFactory.getLogger方法触发。相关代码如下
public final class LoggerFactory {
public static Logger getLogger(String name) {
/**
这里需要获取实现了ILoggerFactory接口的对象
*/
ILoggerFactory iLoggerFactory = getILoggerFactory();
return iLoggerFactory.getLogger(name);
}
public static ILoggerFactory getILoggerFactory() {
if (INITIALIZATION_STATE == UNINITIALIZED) {
synchronized (LoggerFactory.class) {
if (INITIALIZATION_STATE == UNINITIALIZED) {
INITIALIZATION_STATE = ONGOING_INITIALIZATION;
//这里进行绑定,会调用bind()方法
performInitialization();
}
}
}
switch (INITIALIZATION_STATE) {
case SUCCESSFUL_INITIALIZATION:
/**
最终会走到这里,StaticLoggerBinder是桥接包log4j-slf4j-impl-*.jar中的对象,getLoggerFactory()返回了Log4jLoggerFactory对象
*/
return StaticLoggerBinder.getSingleton().getLoggerFactory();
case NOP_FALLBACK_INITIALIZATION:
return NOP_FALLBACK_FACTORY;
case FAILED_INITIALIZATION:
throw new IllegalStateException(UNSUCCESSFUL_INIT_MSG);
case ONGOING_INITIALIZATION:
return SUBST_FACTORY;
}
throw new IllegalStateException("Unreachable code");
}
//绑定流程
private final static void bind() {
//-----------
StaticLoggerBinder.getSingleton();
//-----------
}
}
org.slf4j.impl.StaticLoggerBinder
private StaticLoggerBinder() {
//使用了log4j
loggerFactory = new Log4jLoggerFactory();
}
三、总结
slf4j需要StaticLoggerBinder对象来完成绑定,所以其他的日志框架要想接入slf4j都要定义一个org.slf4j.impl.StaticLoggerBinder对象。 只不过返回的ILoggerFactory实现不一样。