【问题标题】:Is there a way to fire a trigger from System.out.println?有没有办法从 System.out.println 触发触发器?
【发布时间】:2012-03-02 10:15:17
【问题描述】:

这可能是一个非常愚蠢的问题,但是,有没有办法在 Java 中将某些内容打印到控制台并在其他地方监听时触发触发器?

我对触发器或 System 类(或就此而言的 Logger)知之甚少,所以如果有更简单的方法(没有触发器)请告诉我。

我们正在尝试使用 Logger 来记录我们所有的测试。目前,我们一直在使用简单的“System.out.println”来记录控制台中的所有内容,所以我想知道是否可以在打印到它时触发触发器,然后让侦听器将该信息添加到 Logger。

谢谢。

【问题讨论】:

  • 全局搜索 System.out.println( 并替换为适当的 Logger 调用不是更容易吗?
  • 不,System.out.println() 必须保留。记录器无法替换它。此外,我还会做一些其他事情(使用 DEBUG 和 INFO)。

标签: java triggers listen system.out


【解决方案1】:

最直接的方法是

System.setOut(new PrintStream(System.out) {
  public void println(String s) {
    logger.log(s);
    super.println(s);
  }
  // override some other methods?
});

【讨论】:

  • 看起来很有趣,但我不知道它在做什么。你能更具体地介绍一下包装部分吗?
  • 完美,就是这样!还要添加一件事:如果应用程序调用 System.out.println() 并传入对象类型的参数(不是字符串,而是一些特定于应用程序的对象),那么也可以覆盖 public void println(Object o)。
  • 我认为覆盖 write(String) 是捕获所有情况的最有效方法,但我需要深入研究 PrintStream 实现。
  • 很好的答案!我在它周围写了一个单例,这样更容易听
【解决方案2】:

面向方面的编程 (AOP) 可以帮助您实现这种行为。

由于您正在使用 Java,您可以使用 AspectJ(最成熟的 AOP 语言之一)来捕获对 System.out.println() 的所有调用,并“注入”您通知 Logger 类的行为。

下面是 AspectJ 中的一些示例代码,说明它是如何工作的:

pointcut somethingIsBeingLogged(): execution(public static * System.out.println());
before() : somethingIsBeingLogged() {
    // Get the context by joinPoint.getThis();
    // Notify the Logger class
}

您实际上可以停止对System.out.println() 的调用,只让您的 Logger 类进行控制。如果您想采用 AOP 路径,我可以提供更多详细信息。

【讨论】:

  • 如果我一个人工作,我会走你的路。问题是经理希望尽可能保持本地化(他希望我们检查每个文件并手动完成)。所以我正在寻找一种方法来修改主要的抽象类(所有类都调用)并让计算机完成工作。知道这也很有趣。
  • 明白。在这种情况下,尽管听起来很愚蠢,但如何将 System.out.println() 替换为 System.out.println();Logger.log() 以确保控制台都收到消息并通知您的班级?
  • 叹息,我想避免这种情况,因为我必须为调试和错误做同样的事情。我想这可以工作,我可以使用带有捕获组的正则表达式,以便 log() 与 println() 具有相同的字符串。
  • 幸运的是,在我职业生涯的某个阶段,我可以告诉经理们我对他们荒谬的限制的看法,如果他们没有充分的理由,就以正确的方式去做。
【解决方案3】:

这只是 Louis Wasserman 出色答案的一个很好的单例包装器。我的代码可供任何希望使用它的人免费使用。使用它,您可以在任何地方以相当简单的方式获取控制台输出。

public class SystemOutListener {

    private static SystemOutListener singleton;

    public static SystemOutListener GetSingleton() {
        if (singleton == null) {
            singleton = new SystemOutListener();
            singleton.ReplaceStandartSystemOutPrintStream();
        }
        return singleton;
    }
    private ArrayList<ISystemOutObserver> observersList = new ArrayList<>();

    public void AttachSystemOutObserver(ISystemOutObserver observer) {
        observersList.add(observer);
    }

    public void RemoveSystemOutObserver(ISystemOutObserver observer) {
        observersList.remove(observer);
    }

    private void FireSystemOutPrintln(String message) {
        for (int i = 0; i < observersList.size(); i++) {
            java.awt.EventQueue.invokeLater(new HandleSystemOutRunner(observersList.get(i), message));
        }
    }

    private void ReplaceStandartSystemOutPrintStream() {
        System.setOut(new PrintStream(System.out) {
            @Override
            public void println(String s) {
                super.println(s);
                FireSystemOutPrintln(s);
            }
        });
    }

    public interface ISystemOutObserver {
        public void HandleSystemOut(String message);
    }

    private class HandleSystemOutRunner implements Runnable {

        private String message;
        private ISystemOutObserver target;

        public HandleSystemOutRunner(ISystemOutObserver target, String message) {
            this.message = message;
            this.target = target;
        }

        @Override
        public void run() {
            target.HandleSystemOut(message);
        }
    }
}

用法:

SystemOutListener.GetSingleton().AttachSystemOutObserver(/*YOUR OBSERVER*/)

Lambdas(Java 8) 也可以用来代替观察者!

【讨论】:

    【解决方案4】:

    可能距离您需要的内容有一千英里,但您可以在 linux 下使用“watch”之类的东西来寻找特定的文本。如果您要注销文件,您可以设置“监视”来监视文件中的某些文本并相应地发出指令。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-07-13
      • 1970-01-01
      • 2013-08-30
      • 1970-01-01
      相关资源
      最近更新 更多