Java:是否有可能(在运行时)获取未来方法调用的源文件名和行号?

时间:2012-05-16 19:39:06

标签: java swing events logging stack-trace

我正在开发一个正在工作的项目,我的任务是实现一个自定义Java Swing库,只要用户与Swing组件进行交互,就会将事件记录到文件中。换句话说,每当用户与GUI上的按钮,复选框等交互时,事件就会记录到文件中。日志条目必须包含事件发生位置的源文件名和行号。有一个问题:日志记录机制需要在中自动发生,用于由库的开发者外部实现的方法。可以吗?这是我到目前为止所做的:

自定义库动作侦听器:

public abstract class MyActionListener implements ActionListener
{
    // Prevents the developer from implementing the "actionPerformed" method
    @Override
    public final void actionPerformed(ActionEvent e)
    {
        // Do nothing
    }

    // Custom method
    public void actionPerformed(MyActionEvent e)
    {
        doCustomMethod();

        // Tried obtaining the stack trace here but there's no entry
        // in the trace for "doCustomMethod()"
        StackTraceElement [] elements = Thread.currentThread().getStackTrace();
        for (StackTraceElement element : elements)
        {
            // print each element
        }
    }

    // Forces the developer to implement this method
    public abstract void doCustomMethod();
}

自定义库按钮:

public class MyButton extends JButton
{
    ...

    // Custom method
    public void addActionListener(MyActionListener l)
    {
        listenerList.add(MyActionListener.class, l);
    }
}

开发人员创建了GUI:

public class TestGui extends JFrame
{
    TestGui()
    {
        ...

        MyButton button = new MyButton("Push");
        button.addActionListener(new MyActionListener()
        {
            public void doCustomMethod()
            {
                // Want to log this line number and file name,
                // but need the library to do it; NOT the developer.
            }
        });
    }
}

我已经掌握了所有正确的逻辑,以便调用正确的 addActionListener() actionPerformed()方法。我的问题是尝试记录事件。我也尝试过实现自定义Java注释,但它没有用。此外,开发人员必须在构建GUI时包含-processor选项。我们试图让开发人员像Java Swing库一样使用我们的自定义Swing库。我实施的更改对开发人员来说是透明的。

非常感谢任何帮助。

3 个答案:

答案 0 :(得分:1)

也许Logback + SLF4J可以帮助您

首先在你的类路径中放入logback-classic.jar,logback-core.jar和slf4j-api

如果没有默认配置,则有默认配置,但如果您需要更详细的配置,可以添加logback.xml配置文件,如下所示:

<?xml version="1.0" encoding="UTF-8" ?>

<configuration scan="true" scanPeriod="60 seconds">

<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
    <layout class="ch.qos.logback.classic.PatternLayout">
        <pattern>[%d{ISO8601}] [%-5level] \(%F:%L\) - %msg%n</pattern>
    </layout>
</appender>

<logger name="org.hibernate" level="WARN" />
<logger name="org.springframework" level="INFO" />

<root level="INFO">
    <appender-ref ref="CONSOLE" />
</root>

</configuration>

答案 1 :(得分:1)

如何遍历组件树并将侦听器添加到每个组件(JButton等 - 可以与用户交互并且您需要它)?

然后开发人员可以使用简单的JButton(而不是MyButton)。 但是当您使用此方法时 - 您应该在创建所有组件后调用遍历组件方法。如果要添加其他组件,您还可以添加侦听Component#add方法并更新侦听器的ComponentListener。

答案 2 :(得分:0)

如果您可以强制他们在doCustomMethod()实现中调用方法,那么您可以从堆栈跟踪信息中访问行号。否则,您可以使用this.getClass()查找其实现的类名称,并使用ASM ClassReader查找行号/源文件。