log4j 如何使用依赖注入限制对象创建?

sdnqo3pr  于 12个月前  发布在  其他
关注(0)|答案(4)|浏览(123)

我正在创建一个具有自定义日志功能的类,它在内部使用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);
    }
}

字符串
谢谢

daupos2t

daupos2t1#

LoggerObj是静态的,因此只存在于类级别。在第一次调用getLogger之后,变量被初始化,并将继续向其他客户端返回相同的对象。
看起来你想为记录器创建一个工厂,但却创建了一个单例?

vuv7lop3

vuv7lop32#

为什么不直接用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

7z5jn7bk

7z5jn7bk3#

划分基础结构逻辑以分离实体的主要方法是可测试性。
使用构造函数(或setter)注入而不是在对象中创建对象,你可以很容易地用mocks替换这种依赖。但我不认为基于logger的测试是最好的选择。
第二种方法是代码可移植性,但是正如 @Thorbjørn Ravn Andersen 已经提到的,slf4j将更适合这项任务。

p8ekf7hl

p8ekf7hl4#

我不完全确定你想达到什么目的,无论如何,这似乎是错误的:

public static LoggerObject getLogger(String className)
    {
        if (loggerobj==null)
        {
         loggerobj = new LoggerObject(className);
        }
         return loggerobj;
    }

字符串
你实现了一个singleton模式,但是你存储的是第一个getLogger调用中传递的className(“foo”)。这意味着所有对getLogger(“bar”)的后续调用都将返回一个className为“foo”的LoggerObject。如果你想让一个logger来统治所有的logger,那么它的名字可能应该是一个应用常量或可配置的属性,而不是碰巧被日志客户端传递的第一个名字。
Log4J的标准用法是:

private static final Logger LOG = Logger.getLogger(abc.xyz.MyLoggingClient.class);


这将创建一个以参数的完全限定类名作为其名称的记录器。在log4j.properties中,您将拥有以下内容:

log4j.logger.abc.xyz.MyLoggingClient=WARN


请解释你到底想实现什么,你不能用普通的Log4j。

相关问题