簡體   English   中英

如何監控第三方庫的方法執行?

[英]How to monitor method execution at third party library?

我有任務以某種方式監視 logback 庫中的方法調用。 我開始用 spring aop 做這件事。 因此,例如,我應該在 ch.qos.logback.classic.Logger 類中捕獲所有方法的執行。 這是我的方面:

@Aspect
@Configuration
public class LogbackAspect {

    @Before(value = "execution(* ch.qos.logback.classic.Logger.*(..))")
    public void getInfo(JoinPoint joinPoint) {
         System.out.println("+++++AOP " + joinPoint.getSignature().getName());
}
}

但是暫時不行,那么,有沒有可能用spring aop攔截方法執行呢? 或者有一些更好的方法來做到這一點?

不幸的是,您只能編織自己的代碼。

Brendon 的回答不正確,因為它專注於 Android。 在 Windows、MacOS、Linux 等具有普通 Java 的平台上,您可以攔截第三方代碼,條件如下:

  • 您使用完整的 AspectJ,而不是 Spring AOP。 AspectJ 可以在沒有 Spring 的情況下使用,也可以在 Spring 項目中使用。
  • 您使用 LTW(加載時編織),通常通過 JVM 參數-javaagent:/path/to/aspectjweaver.jar ,並正確配置aop.xml
  • 作為替代方案,您可以通過命令行或AspectJ Maven 插件直接使用 AspectJ 編譯器ajc來進行二進制編織,即將方面代碼編織到您的 3rd 方庫中,創建新的編織類文件並將它們重新打包到新的 JAR 中. 然后您將使用該 JAR 代替原始文件。 (順便說一句,如果庫是您可以隨應用程序一起交付和安裝的東西,而不是某些無法替換或覆蓋的系統類/庫,那么這也適用於 Android。)

如果您對使用 Java 命令行參數沒有限制,我建議使用 LTW 而不是二進制編織。 Spring 手冊中甚至有一章描述了如何直接在 Spring 中使用它。


更新:這是一個MCVE,向您展示如何在純 Java + AspectJ LTW 中執行此操作。

讓我們在安裝了 AJDT(AspectJ 開發工具)的 Eclipse 中創建一個 AspectJ 項目。 當然,您也可以使用 AspectJ Maven 插件創建 Maven 項目,甚至不使用,因為如果您通過-javaagent:/path/to/aspectjweaver.jar使用 LTW,實際上您不需要 AspectJ 編譯器。 我的示例項目具有以下結構(Eclipse 布局,而不是 Maven,我只是快速完成):

Eclipse AspectJ 項目

文件內容如下。

src/de/scrum_master/app/Application.java

package de.scrum_master.app;

import org.slf4j.LoggerFactory;

import ch.qos.logback.classic.Logger;

public class Application {
  private static final Logger logger = (Logger) LoggerFactory.getLogger(Application.class);

  public static void main(String[] args) {
    logger.info("Example log from {}", Application.class.getSimpleName());
  }
}

源代碼/logback.xml

<configuration>
  <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
    <encoder>
      <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
    </encoder>
  </appender>

  <root level="debug">
    <appender-ref ref="STDOUT" />
  </root>
</configuration>

src/de/scrum_master/aspect/LogbackAspect.aj(或簡單的 LogbackAspect.java)

package de.scrum_master.aspect;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;

@Aspect
public class LogbackAspect {
  @Before(value = "execution(* ch.qos.logback.classic.Logger.*(..))")
  public void getInfo(JoinPoint joinPoint) {
    System.out.println(joinPoint);
  }
}

src/META-INF/aop.xml

<?xml version="1.0" encoding="UTF-8"?>
<aspectj>
  <aspects>
    <aspect name="de.scrum_master.aspect.LogbackAspect" />
  </aspects>
  <weaver options="-verbose -showWeaveInfo" />
</aspectj>

現在為Application創建一個簡單的 Java 運行配置並將 Java 代理添加到命令行:

AspectJ LTW 運行配置

現在運行程序,控制台日志將是這樣的:

[AppClassLoader@18b4aac2] info AspectJ Weaver Version 1.9.5 built on Thursday Nov 28, 2019 at 11:28:53 PST
[AppClassLoader@18b4aac2] info register classloader sun.misc.Launcher$AppClassLoader@18b4aac2
[AppClassLoader@18b4aac2] info using configuration /C:/Users/alexa/Documents/java-src/SO_AJ_LTW_Logback_60295366/bin/META-INF/aop.xml
[AppClassLoader@18b4aac2] info register aspect de.scrum_master.aspect.LogbackAspect
[AppClassLoader@18b4aac2] weaveinfo Join point 'method-execution(ch.qos.logback.classic.Level ch.qos.logback.classic.Logger.getEffectiveLevel())' in Type 'ch.qos.logback.classic.Logger' (Logger.java:109) advised by before advice from 'de.scrum_master.aspect.LogbackAspect' (LogbackAspect.aj)
[AppClassLoader@18b4aac2] weaveinfo Join point 'method-execution(int ch.qos.logback.classic.Logger.getEffectiveLevelInt())' in Type 'ch.qos.logback.classic.Logger' (Logger.java:113) advised by before advice from 'de.scrum_master.aspect.LogbackAspect' (LogbackAspect.aj)
[AppClassLoader@18b4aac2] weaveinfo Join point 'method-execution(ch.qos.logback.classic.Level ch.qos.logback.classic.Logger.getLevel())' in Type 'ch.qos.logback.classic.Logger' (Logger.java:117) advised by before advice from 'de.scrum_master.aspect.LogbackAspect' (LogbackAspect.aj)
(...)
[AppClassLoader@18b4aac2] weaveinfo Join point 'method-execution(java.lang.Object ch.qos.logback.classic.Logger.readResolve())' in Type 'ch.qos.logback.classic.Logger' (Logger.java:787) advised by before advice from 'de.scrum_master.aspect.LogbackAspect' (LogbackAspect.aj)
[AppClassLoader@18b4aac2] info processing reweavable type de.scrum_master.aspect.LogbackAspect: de\scrum_master\aspect\LogbackAspect.aj
[AppClassLoader@18b4aac2] info successfully verified type de.scrum_master.aspect.LogbackAspect exists.  Originates from de\scrum_master\aspect\LogbackAspect.aj
execution(void ch.qos.logback.classic.Logger.setLevel(Level))
execution(void ch.qos.logback.classic.Logger.setLevel(Level))
execution(String ch.qos.logback.classic.Logger.toString())
execution(void ch.qos.logback.classic.Logger.addAppender(Appender))
execution(Logger ch.qos.logback.classic.Logger.getChildByName(String))
execution(Logger ch.qos.logback.classic.Logger.createChildByName(String))
execution(Logger ch.qos.logback.classic.Logger.getChildByName(String))
execution(Logger ch.qos.logback.classic.Logger.createChildByName(String))
execution(Logger ch.qos.logback.classic.Logger.getChildByName(String))
execution(Logger ch.qos.logback.classic.Logger.createChildByName(String))
execution(Logger ch.qos.logback.classic.Logger.getChildByName(String))
execution(Logger ch.qos.logback.classic.Logger.createChildByName(String))
execution(void ch.qos.logback.classic.Logger.info(String, Object))
execution(void ch.qos.logback.classic.Logger.filterAndLog_1(String, Marker, Level, String, Object, Throwable))
execution(void ch.qos.logback.classic.Logger.buildLoggingEventAndAppend(String, Marker, Level, String, Object[], Throwable))
execution(String ch.qos.logback.classic.Logger.getName())
execution(LoggerContext ch.qos.logback.classic.Logger.getLoggerContext())
execution(void ch.qos.logback.classic.Logger.callAppenders(ILoggingEvent))
execution(int ch.qos.logback.classic.Logger.appendLoopOnAppenders(ILoggingEvent))
execution(int ch.qos.logback.classic.Logger.appendLoopOnAppenders(ILoggingEvent))
execution(int ch.qos.logback.classic.Logger.appendLoopOnAppenders(ILoggingEvent))
execution(int ch.qos.logback.classic.Logger.appendLoopOnAppenders(ILoggingEvent))
execution(int ch.qos.logback.classic.Logger.appendLoopOnAppenders(ILoggingEvent))
16:04:52.791 [main] INFO  de.scrum_master.app.Application - Example log from Application

我認為這正是你想要的。 請參閱Spring 手冊以了解如何在那里配置 AspectJ LTW。

檢查這個其他答案使用 AspectJ 在 android 中攔截第三方函數

不幸的是,您只能編織自己的代碼。

但是,根據您實際需要使用 Logback 做什么,您可以創建一個自定義 Appender 並在其中執行您需要的操作?

更新

如果您想記錄這些異常的某種形式的指標,您可以根據 logstash-logback 文檔配置 StatusListener

https://github.com/logstash/logstash-logback-encoder#status-listeners

有了這個,您可以接收事件,並記錄您需要的任何指標

我嘗試使用上面說的配置。 但我想從 tomcat lib 文件夾中編織一個 3rd 方 jar。 在這種情況下,這是行不通的。 誰能建議我們如何實現這一目標?

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM