gpt4 book ai didi

java - 如何监控第三方库的方法执行?

转载 作者:行者123 更新时间:2023-12-01 16:42:37 30 4
gpt4 key购买 nike

我有任务以某种方式监视 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来拦截方法执行呢?或者有更好的方法吗?

最佳答案

Unfortunately, you can only weave your own code.

Brendon 的答案不正确,因为它主要针对 Android。在 Windows、MacOS、Linux 等具有普通 Java 的平台上,您可以拦截第三方代码,前提是满足以下条件:

  • 您使用完整的 AspectJ,而不是 Spring AOP。 AspectJ 可以在没有 Spring 的情况下使用,也可以在 Spring 项目中使用。
  • 您通常通过 JVM 参数 -javaagent:/path/to/aspectjweaver.jar 使用 LTW(加载时编织),并正确配置 aop.xml
  • 作为替代方案,您可以直接通过命令行或通过 AspectJ Maven 插件 使用 AspectJ 编译器 ajc 来进行二进制编织,即将方面代码编织到您的第三个中party 库,创建新的 knitted 类文件并将它们重新打包到新的 JAR 中。然后您可以使用该 JAR 来代替原来的 JAR。 (顺便说一句,如果该库是您可以随应用程序一起交付和安装的库,而不是无法替换或覆盖的系统类/库,那么这也适用于 Android。)

如果您没有使用 Java 命令行参数的限制,我建议您使用 LTW 而不是二进制编织。 Spring手册中甚至有一章介绍了如何在Spring中直接使用。

<小时/>

更新:这是一个MCVE向您展示如何在普通 Java + AspectJ LTW 中做到这一点。

让我们在 Eclipse 中创建一个安装了 AJDT(AspectJ 开发工具)的 AspectJ 项目。当然,您也可以使用 AspectJ Maven 插件创建 Maven 项目,甚至不使用 AspectJ Maven 插件,因为实际上,如果您通过 -javaagent:/path/to/aspectjweaver.jar 使用 LTW,则不需要 AspectJ 编译器。我的示例项目具有以下结构(Eclipse 布局,不是 Maven,我只是很快就完成了):

Eclipse AspectJ project

文件内容如下。

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

src/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 run configuration

现在运行程序,控制台日志将如下所示:

[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 manual以了解如何在那里配置 AspectJ LTW。

关于java - 如何监控第三方库的方法执行?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60295366/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com