如何通过某些依赖注入来限制对象创建?

问题描述 投票:0回答:4

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

谢谢

java log4j
4个回答
0
投票

LoggerObj 是静态的,因此仅存在于类级别。第一次调用 getLogger 后,变量被初始化,并将继续向其他客户端返回相同的对象。

看起来您想为记录器创建一个工厂,但却创建了一个单例?


0
投票

你为什么不直接使用

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


0
投票

将基础设施逻辑划分为单独实体的主要方法是可测试性。

使用构造函数(或设置器)注入而不是在对象中创建对象,您可以轻松地用模拟替换这种依赖关系。但我不认为基于记录器进行测试是最好的选择。

第二种方法是代码可移植性,但正如 @Thorbjørn Ravn Andersen 已经提到的那样,slf4j 会更适合这项任务。


0
投票

我不完全确定你想要实现什么,无论如何这似乎是错误的:

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 无法实现的目标。

© www.soinside.com 2019 - 2024. All rights reserved.