Много раз мы находим, что 3-й партии библиотеки будут писать System.out или System.err. Это, вероятно, следует быть проще перенаправить их на общих рамок лесозаготовительных, но это не так.
<Р> Ниже вы найдете класс, который вы можете использовать для достижения именно это. Класс является экземпляром PrintWriter и может быть реализован и используется в качестве System.out и System.err PrintWriter. Это будет перенаправлять все STDOUT и STDERR сообщения на Commons Logging. Это будет также искать вызывающий класс и получить регистратор под названием: com.domain.
Class (возможно, с определенной пользователем префикса или суффикса, например: STDOUT.com.domain.Class или com.domain.Class.STDOUT)
<р> Для простоты использования вы можете использовать статические фабричные методы, которые автоматически зарегистрировать класс по STDOUT STDERR или соответственно. Ниже приведены несколько типичных примеров использования
<р> Несколько замечаний о том, как это работает: Каталог
<р> Пример: в начале вашего приложения:
статической силы основных (String [] аргументы) {общественных CommonsLoggingPrintStream.registerOnStdout (NULL , "STDOUT"); CommonsLoggingPrintStream.registerOnStderr (нуль ", STDERR"); //...
} <р> Пример использования: Весной (добавить следующее в ваш контексте запуска, использует методы заводе, так код не требуется) :
STDOUTSTDERR <р> Класс код (примечание: вы можете свободно изменять пакет /имя класса, они используются в коде anaylize трассировки стека, но они выглядели динамически)
пакетов mycommons.logging, импорт java.io.ByteArrayOutputStream, импорт java.io.IOException, импорт java.io.PrintStream, импорт java.util.Locale, импорт java.util.concurrent.locks.ReentrantLock; org.apache.commons.logging.
LogFactory импорта; /** * Этот класс перенаправляет все запросы к PrintStream (используется STDOUT и STDERR) * и отправляет их на Commons Logging. * * Метод призвание PrintStream определяется путем анализа стека. * * Используйте удобные методы registerOnStdout и registerOnStderr автоматически * создать экземпляр этого класса и зарегистрировать его на поток для перенаправления * Commons Logging. * * Пример типичного использования: * * * статической силы основных (String [] аргументы) {* общественные CommonsLoggingPrintStream.registerOnStdout (нуль ", STDOUT"); * CommonsLoggingPrintStream.
registerOnStderr (нуль ", STDERR"); * //*} ... * * * Примечание для странных случаях: Если вы сделать несколько звонков, чтобы методы, которые не вызывают * флеш, как описано в PrintWriter (например, добавить (Char)) метод вызова * будет определяться только по конечному вызова, который вызывает флеш или флеш называет () напрямую. Также обратите внимание, что * в этом случае вы должны синхронизировать доступ к этим методам, поскольку они не будут потокобезопасными.
* Это правило, рекомендуется только методов обработки вызовов, которые генерируют автоматической флеш, как описано * в PrintWriter Javadocs * /общественного класса CommonsLoggingPrintStream распространяется PrintStream {LoggingOutputStream OutputStream; частный замок ReentrantLock = новый ReentrantLock (); /** * Вы можете использовать новый экземпляр войти все методы PrintStream в Commons Logging.
* Сообщения будут записаны при CommonsLogging флеш () вызывается с использованием * те же правила, PrintStream использует с AutoFlush = правда * * @ параметров prependName A имя предваряется класса (нулевой) ни для имени, как в: registerOnStdout ("STDOUT" нулевые результаты) в сообщении журнала, такие как: ИНФОРМАЦИЯ STDOUT.org.mydomain.MyClass - Войти сообщение * @ параметров postpendName A имя postpended к классу (нулевой) ни для имен, как в: registerOnStdout (NULL, "стандартный вывод") Результаты в сообщении журнала, таких как: ИНФОРМАЦИЯ org.mydomain.MyClass.
STDOUT -Log сообщения * /общественного CommonsLoggingPrintStream (String prependName, String postpendName) {это (новый LoggingOutputStream (prependName, postpendName, CommonsLoggingPrintStream.class.getCanonicalName ())); } Личное CommonsLoggingPrintStream (LoggingOutputStream лос) {супер (лос, правда); this.
outputStream = лос; } /** * Метод Удобство - Создает новый экземпляр * CommonsLoggingPrintStream и регистрирует его на STDOUT * * @ параметров prependName A имя предваряется класса (нулевой) ни для имени, как в: registerOnStdout ("стандартный вывод", NULL) приводит сообщение журнала, такие как: INFO STDOUT.org.mydomain.MyClass - Войти сообщение * @ параметров postpendName A имя postpended к классу (нулевой) ни для имен, как в: registerOnStdout (нуль ", STDOUT") результаты в сообщении журнала такого как: ИНФОРМАЦИЯ org.mydomain.MyClass.
STDOUT -Log сообщение *return ссылку на объект, созданный CommonsLoggingPrintStream, могут быть проигнорированы в большинстве ситуаций * /общественности статической CommonsLoggingPrintStream registerOnStdout (String prependName, String postpendName) {CommonsLoggingPrintStream ссылка = новый CommonsLoggingPrintStream ( prependName, postpendName); System.
setOut (ссылка); вернуться арбитру; } /** * Метод Удобство - Создает новый экземпляр * CommonsLoggingPrintStream и регистрирует его на STDERR * * @ параметров prependName A имя предваряется класса (нулевой) ни для имени, как в: registerOnStdout ("STDERR", NULL) результаты в сообщение журнала, такие как: INFO STDERR.org.mydomain.MyClass - Войти сообщение * @ параметров postpendName A имя postpended к классу (нулевой) ни для имен, как в: registerOnStdout (нуль ", STDERR") результаты в сообщении журнала такого как: ИНФОРМАЦИЯ org.mydomain.MyClass.
STDERR -Log сообщение *return ссылку на объект, созданный CommonsLoggingPrintStream, могут быть проигнорированы в большинстве ситуаций * /общественности статической CommonsLoggingPrintStream registerOnStderr (String prependName, String postpendName) {CommonsLoggingPrintStream ссылка = новый CommonsLoggingPrintStream ( prependName, postpendName); System.setErr (ссылка); вернуться арбитру; } /** * Этот класс требуется для того, чтобы сделать использование PrintWriters гарантия *, что на одном уровне будет называться в соответствующее время.
Мы вывешиваем данные * Commons Loggging только после промывки () вызывается на завернутый выход * поток по PrintWriter. * * /Частный статический класс LoggingOutputStream распространяется ByteArrayOutputStream {личное Струнный currentCallerName; частный Строка prependName = NULL; частный Строка postpendName = NULL; частный Строка outerClassName = NULL; //Это динамически, так что изменения в пакет или имя класса не влияют на функциональность общественного LoggingOutputStream (String prependName, String postpendName, String outerClassName) {this.
prependName = (prependName! = NULL &&! PrependName.isEmpty ()) ? prependName + "." : ""; this.postpendName = (postpendName! = NULL &&! postpendName.isEmpty ())? "." + PostpendName: ""; this.outerClassName = outerClassName; } @ Override общественного недействительными флеш () бросает IOException {super.flush (); //Вход в результате байт после промывки () называется. Мы можем полагаться на это, потому что //мы создали PrintStream с вариантом AutoFlush включен. //Если массив байт записывается он может содержать несколько строк String [] = logMessages this.toString () раскол ("\\ п").
для (String сообщение: logMessages) {LogFactory.getLog (currentCallerName) .info (message.trim ()); }} Пустота setNameOfCaller () {Boolean = False reachedCallToOutterClass; StackTraceElement [] = стек Thread.currentThread () getStackTrace (). //Перебор элементов трассировки стека, пока не найдем "java.io.PrintStream" //и вернуть первый полностью квалифицированное-имя-класса после вызовов PrintStream для (StackTraceElement е: стека) {если (e.getClassName () .equals (outerClassName)) {reachedCallToOutterClass = TRUE; Продолжать; } еще, если (reachedCallToOutterClass) {this.
currentCallerName = prependName + e.getClassName () + postpendName; вернуть; }} This.currentCallerName = "unknown.classname"; //Недоступен Код (или так держит теория)}} /** * Передает вызов на к outputStream.setNameOfCaller () только * если синхронная блокировка на этом принадлежит один раз. Если это * принадлежит более чем один раз, то это обратный вызов изнутри * PrintWriter, ситуация, которая будет трудно /невозможно * для определения метода вызова, и не надо, так как * первый вызов setNameOfCaller () это все, что было * необходимы для определения метода вызова.
* /Частный пустота setNameOfCaller (ReentrantLock замок) {если (lock.getHoldCount ()>