Java 有没有办法从System.out.println启动触发器?

Java 有没有办法从System.out.println启动触发器?,java,triggers,listen,system.out,Java,Triggers,Listen,System.out,这可能是一个非常愚蠢的问题,但是,有没有一种方法可以在Java中向控制台输出某个内容时触发触发器,并在其他地方侦听它 我对触发器或系统类(或记录器)了解很少,因此如果有更简单的方法(没有触发器)请告诉我 我们正在尝试使用日志记录器记录所有测试。目前,我们一直在使用简单的“System.out.println”来记录控制台中的所有内容,因此我想知道是否可以在打印到其中的内容时触发触发器,然后让侦听器将该信息添加到记录器中 谢谢。可能离您需要的东西有一千英里远,但是您可以在linux下使用类似“wa

这可能是一个非常愚蠢的问题,但是,有没有一种方法可以在Java中向控制台输出某个内容时触发触发器,并在其他地方侦听它

我对触发器或系统类(或记录器)了解很少,因此如果有更简单的方法(没有触发器)请告诉我

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


谢谢。

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

面向方面编程(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.setOut(new PrintStream(System.out) {
  public void println(String s) {
    logger.log(s);
    super.println(s);
  }
  // override some other methods?
});

这只是一个很好的单件包装路易·沃瑟曼的优秀答案。任何想使用我的代码的人都可以免费使用我的代码。使用它,您可以以相当简单的方式在任何地方获得控制台输出

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);
        }
    }
}

Lambdas(java8)也可以用来代替observer

全局搜索
System.out.println(
并替换为适当的记录器调用不是更容易吗?不,System.out.println()必须保留。记录器无法替换它。此外,我还将对此执行其他操作(使用调试和信息)。如果我是一个人工作,我会选择你的方式。问题是经理想让事情尽可能地原生(他希望我们检查每个文件并手动进行)。所以我正在寻找一种方法,只修改主抽象类(所有类都调用)让计算机来完成这项工作。知道。理解也很有趣。在这种情况下,尽管听起来很愚蠢,用
System.out.println()
替换
System.out.println();Logger.log()怎么样
为了确保控制台都能收到消息并通知您的类?唉,我想避免这样做,因为我必须对调试和错误执行相同的操作。我想这可能行得通,我可以使用带有捕获组的正则表达式,以便log()具有与println()相同的字符串.幸运的是,在我的职业生涯中,我可以告诉经理们我对他们荒谬的限制的看法,如果他们没有充分的理由,我会以正确的方式去做。看起来很有趣,但我不知道它在做什么。你能更具体地描述包装器部分吗?很好,就是这样!还有一件事要补充:如果应用程序函数调用
System.out.println()
传入一个object类型的参数(不是String而是一些特定于应用程序的对象),然后可以重写
public void println(object o)
。我认为重写
write(String)
是捕获所有案例的最有效的方法,但我需要深入研究
PrintStream
实现。回答得很好!我已经编写了一个关于它的单例,以便更容易聆听
SystemOutListener.GetSingleton().AttachSystemOutObserver(/*YOUR OBSERVER*/)