今天读了一下dubbo的源码,dubbo源码本身主要包括以下几个部分(包):common、config、container、monitor、registry、remoting、rpc,其中今天要说的日志适配器模式就在common包中。
首先我们来看日志的调用方式如下:
public class DubboRegistry extends FailbackRegistry {
private final static Logger logger = LoggerFactory.getLogger(DubboRegistry.class);
// doSomethings
}
LoggerFactory是dubbo自己封装好的可以适配很多种日志组件的工厂,下面来看下dubbo是怎么在日志服务方面使用适配器模式,可以让很多日志组件适用于dubbo:
1、在Factory中通过static静态代码块的方式,从dubbo的配置文件中读取dubbo要使用的日志组件,Factory中有LoggerAdapter对象存放对应日志的适配器,判断读取的日志后,new相应的适配器赋值给LoggerAdapter对象,如下:
/**
* 日志输出器工厂
*
* @author william.liangf
*/
public class LoggerFactory {
private LoggerFactory() {
}
private static volatile LoggerAdapter LOGGER_ADAPTER;
private static final ConcurrentMap<String, FailsafeLogger> LOGGERS = new ConcurrentHashMap<String, FailsafeLogger>();
// 查找常用的日志框架
static {
String logger = System.getProperty("dubbo.application.logger");
if ("slf4j".equals(logger)) {
setLoggerAdapter(new Slf4jLoggerAdapter());
} else if ("jcl".equals(logger)) {
setLoggerAdapter(new JclLoggerAdapter());
} else if ("log4j".equals(logger)) {
setLoggerAdapter(new Log4jLoggerAdapter());
} else if ("jdk".equals(logger)) {
setLoggerAdapter(new JdkLoggerAdapter());
} else {
try {
setLoggerAdapter(new Log4jLoggerAdapter());
} catch (Throwable e1) {
try {
setLoggerAdapter(new Slf4jLoggerAdapter());
} catch (Throwable e2) {
try {
setLoggerAdapter(new JclLoggerAdapter());
} catch (Throwable e3) {
setLoggerAdapter(new JdkLoggerAdapter());
}
}
}
}
}
}
2、每一个日志的适配器类都实现了LoggerAdapter接口,该接口定义如下:
/**
* 日志输出器供给器
*
* @author william.liangf
*/
@SPI
public interface LoggerAdapter {
/**
* 获取日志输出器
*
* @param key 分类键
* @return 日志输出器, 后验条件: 不返回null.
*/
Logger getLogger(Class<?> key);
/**
* 获取日志输出器
*
* @param key 分类键
* @return 日志输出器, 后验条件: 不返回null.
*/
Logger getLogger(String key);
/**
* 设置输出等级
*
* @param level 输出等级
*/
void setLevel(Level level);
/**
* 获取当前日志等级
*
* @return 当前日志等级
*/
Level getLevel();
/**
* 获取当前日志文件
*
* @return 当前日志文件
*/
File getFile();
/**
* 设置输出日志文件
*
* @param file 输出日志文件
*/
void setFile(File file);
}
3、相应的具体日志适配器实现该接口,实现具体的LoggerAdapter中定义的方法,比如核心的getLogger等,如下图:
public class Slf4jLoggerAdapter implements LoggerAdapter {
public Logger getLogger(String key) {
return new Slf4jLogger(org.slf4j.LoggerFactory.getLogger(key));
}
public Logger getLogger(Class<?> key) {
return new Slf4jLogger(org.slf4j.LoggerFactory.getLogger(key));
}
}
通过这样的适配,可以使日志组件灵活的应用于dubbo,而且可以灵活的添加新的日志组件应用到dubbo框架中,比如现在比较流行的logback(log4j的升级版本),我们就可以新添加一个Logback的Adapter适配器,然后实现LoggerAdapter的接口,通过logback实现具体的方法定义,然后在Factory中在使用的时候直接new LogBackAdapter就可以使用了。
以上就是dubbo框架目前看到的设计模式,继续学习中.......................