我正在创建一个具有自定义日志记录功能的类,该类在内部使用Log4J。
如果某个类需要日志记录功能,我会将类的名称传递给此
LoggerObject
的构造函数。
我想知道如何在不将类名传递给对象的情况下限制对象创建。我尝试了一个解决方案,但我不确定这是实现此目标的正确方法。
public class LoggerObject {
private Logger logger;
private static LoggerObject loggerobj;
private ConstantDataManager constantdatamanger;
//Default Log4J_FILE Path
private LoggerObject(String className) {
try {
DOMConfigurator.configure(
this.getClass()
.getClassLoader()
.getResource(constantdatamanger.LOG4J_FILE)
);
logger =Logger.getLogger(className);
} catch(Exception ex) {
System.out.println("DOMConfigurator could not find file"+ex.getMessage());
}
}
public static LoggerObject getLogger(String className) {
if (loggerobj==null) {
loggerobj = new LoggerObject(className);
}
return loggerobj;
}
public void info(Object message) {
logger.info(message);
}
public void info(Object message, Throwable t) {
logger.info(message, t);
}
public void error(Object message) {
logger.error(message);
}
public void error(Object message, Throwable t) {
logger.error(message,t);
}
public void debug(Object message) {
logger.debug(message);
}
public void debug(Object message, Throwable t) {
logger.debug(message,t);
}
public void warn(Object message) {
logger.warn(message);
}
public void warn(Object message, Throwable t) {
logger.warn(message,t);
}
public void fatal(Object message) {
logger.fatal(message);
}
public void fatal(Object message, Throwable t) {
logger.fatal(message,t);
}
}
谢谢
LoggerObj 是静态的,因此仅存在于类级别。第一次调用 getLogger 后,变量被初始化,并将继续向其他客户端返回相同的对象。
看起来您想为记录器创建一个工厂,但却创建了一个单例?
你为什么不直接使用
Log logger = LogFactory.getLog(className);
?
如果您想自动向日志添加更多数据,您可以使用 LoggerObject,但也许您应该传递类而不是类名,如下所示
class LoggerObject<T> {
private LoggerObject(Class<T> clazz){
...
}
}
如果你想限制哪些类通过,可以使用
class LoggerObject<T extends SomeBaseClass>
。
编辑:
你应该知道这一点:
private static LoggerObject loggerobj;
public static LoggerObject getLogger(String className)
{
if (loggerobj==null)
{
loggerobj = new LoggerObject(className);
}
return loggerobj;
}
这将为第一次调用返回正确的记录器,然后忽略传递的
className
。
将基础设施逻辑划分为单独实体的主要方法是可测试性。
使用构造函数(或设置器)注入而不是在对象中创建对象,您可以轻松地用模拟替换这种依赖关系。但我不认为基于记录器进行测试是最好的选择。
第二种方法是代码可移植性,但正如 @Thorbjørn Ravn Andersen 已经提到的那样,slf4j 会更适合这项任务。
我不完全确定你想要实现什么,无论如何这似乎是错误的:
public static LoggerObject getLogger(String className)
{
if (loggerobj==null)
{
loggerobj = new LoggerObject(className);
}
return loggerobj;
}
您实现了一个 singleton 模式,但是您正在存储在第一个 getLogger 调用中传递的 className (“foo”)。这意味着对 getLoggger("bar") 的所有后续调用都将返回类名为“foo”的 LoggerObject。如果您希望一个记录器统治所有记录器,那么它的名称可能应该是应用程序常量或可配置属性,而不是恰好由记录客户端传递的第一个名称。
常规的 Log4J 习惯用法是:
private static final Logger LOG = Logger.getLogger(abc.xyz.MyLoggingClient.class);
这将创建一个记录器,其名称为参数的完全限定类名。在 log4j.properties 中你会有类似的东西:
log4j.logger.abc.xyz.MyLoggingClient=WARN
请解释一下您到底想要实现哪些使用普通 Log4j 无法实现的目标。