Java 记录实例的任何方法调用
是否可以记录类实例的任何方法调用?我有以下的例子:Java 记录实例的任何方法调用,java,reflection,proxy,interceptor,Java,Reflection,Proxy,Interceptor,是否可以记录类实例的任何方法调用?我有以下的例子: InputStream serverInputStream = this.serverProcess.getInputStream(); 我想看看在运行时的某个给定时间,在serverInputStream中调用了什么方法。我认为解决这个问题的办法是反射,特别是代理。我已经试过让它工作,但无法让它运行 我想到了一个类似的代码: MyInterceptor myInterceptor = new MyInterceptor(this.serve
InputStream serverInputStream = this.serverProcess.getInputStream();
我想看看在运行时的某个给定时间,在serverInputStream
中调用了什么方法。我认为解决这个问题的办法是反射,特别是代理。我已经试过让它工作,但无法让它运行
我想到了一个类似的代码:
MyInterceptor myInterceptor = new MyInterceptor(this.serverProcess.getInputStream());
InputStream serverInputStream = myInterceptor.getInterceptedInstance();
serverInputStream.methodOne();
serverInputStream.methodTwo();
serverInputStream.methodThree();
myInterceptor.printIntercepts();
1. InputStream.InputStream();
2. InputStream.methodOne();
3. InputStream.methodTwo();
4. InputStream.methodThree();
具有与此类似的结果:
MyInterceptor myInterceptor = new MyInterceptor(this.serverProcess.getInputStream());
InputStream serverInputStream = myInterceptor.getInterceptedInstance();
serverInputStream.methodOne();
serverInputStream.methodTwo();
serverInputStream.methodThree();
myInterceptor.printIntercepts();
1. InputStream.InputStream();
2. InputStream.methodOne();
3. InputStream.methodTwo();
4. InputStream.methodThree();
这可能吗?这里有两个选项:
java.lang.reflect.Proxy只能生成一组接口的实现,而字节码操作库也可以修补现有类。这里有两个选项:
java.lang.reflect.Proxy只能生成一组接口的实现,而字节码操作库也可以修补现有的类。为什么不能只编写一个?然后,您只需将要观看的
InputStream
包装为其中一个
class LoggingInputStream extends InputStream {
private final InputStream original;
public LoggingInputStream(InputStream original) {
super();
this.original = original;
}
@Override
public int read(byte[] b) throws IOException {
// Logging here - and below.
return super.read(b);
}
@Override
public int read(byte[] b, int off, int len) throws IOException {
return super.read(b, off, len);
}
@Override
public long skip(long n) throws IOException {
return super.skip(n);
}
@Override
public int available() throws IOException {
return super.available();
}
@Override
public void close() throws IOException {
super.close();
}
@Override
public synchronized void mark(int readlimit) {
super.mark(readlimit);
}
@Override
public synchronized void reset() throws IOException {
super.reset();
}
@Override
public boolean markSupported() {
return super.markSupported();
}
@Override
public int read() throws IOException {
return original.read();
}
}
这是IntelliJ自动生成的。有什么原因不能只写一个吗?然后,您只需将要观看的
InputStream
包装为其中一个
class LoggingInputStream extends InputStream {
private final InputStream original;
public LoggingInputStream(InputStream original) {
super();
this.original = original;
}
@Override
public int read(byte[] b) throws IOException {
// Logging here - and below.
return super.read(b);
}
@Override
public int read(byte[] b, int off, int len) throws IOException {
return super.read(b, off, len);
}
@Override
public long skip(long n) throws IOException {
return super.skip(n);
}
@Override
public int available() throws IOException {
return super.available();
}
@Override
public void close() throws IOException {
super.close();
}
@Override
public synchronized void mark(int readlimit) {
super.mark(readlimit);
}
@Override
public synchronized void reset() throws IOException {
super.reset();
}
@Override
public boolean markSupported() {
return super.markSupported();
}
@Override
public int read() throws IOException {
return original.read();
}
}
这是IntelliJ自动生成的。我想尝试一下Java方面。通过定义一些切入点,您可以监视或劫持其他类方法的行为,截取参数,计算方法被调用的次数 让我们举个例子:
package org.bpa.fd;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
@Aspect
public class ListAspect {
@Pointcut("call(public * java.io.InputStream.*(..))")
public void inputStreamMethod() {
}
@Before("inputStreamMethod()")
public void anyMethod(JoinPoint jp) {
System.out.println(jp.toLongString());
}
}
通过这个切入点,您将看到对InputStream类的公共方法的任何调用。JointPoint还存储方法参数,以获得更完整的概述
您可以使用gradle导入此库:
buildscript {
repositories {
maven {
url "https://maven.eveoh.nl/content/repositories/releases"
}
}
dependencies {
classpath "nl.eveoh:gradle-aspectj:2.0"
}
}
project.ext {
aspectjVersion = '1.8.12'
}
apply plugin: 'aspectj'
摘自:我想尝试一下Java方面。通过定义一些切入点,您可以监视或劫持其他类方法的行为,截取参数,计算方法被调用的次数 让我们举个例子:
package org.bpa.fd;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
@Aspect
public class ListAspect {
@Pointcut("call(public * java.io.InputStream.*(..))")
public void inputStreamMethod() {
}
@Before("inputStreamMethod()")
public void anyMethod(JoinPoint jp) {
System.out.println(jp.toLongString());
}
}
通过这个切入点,您将看到对InputStream类的公共方法的任何调用。JointPoint还存储方法参数,以获得更完整的概述
您可以使用gradle导入此库:
buildscript {
repositories {
maven {
url "https://maven.eveoh.nl/content/repositories/releases"
}
}
dependencies {
classpath "nl.eveoh:gradle-aspectj:2.0"
}
}
project.ext {
aspectjVersion = '1.8.12'
}
apply plugin: 'aspectj'
摘自:如果您想做一些类似Java动态代理的事情,那么它可能是一种替代解决方案。它真的很轻,使用方便
Maven配置:
<dependency>
<groupId>com.ericsson.commonlibrary</groupId>
<artifactId>proxy</artifactId>
<version>1.2.0</version>
</dependency>
com.ericsson.commonlibrary
代理
1.2.0
满足您的请求的代码示例:
public class ProxyExample {
public static void main(String[] args) {
SomeImpl proxy = Proxy.intercept(new SomeImpl(), new MyInterceptor());
proxy.log("hello world");
//Output:
//SomeImpl.log
//hello world
}
public static class SomeImpl {
public void log(String log) {
System.out.println(log);
}
}
public static class MyInterceptor implements Interceptor {
@Override
public Object intercept(Invocation invocation) throws Throwable {
System.out.println(invocation.getThis().getClass().getSuperclass().getSimpleName() + "." + invocation.getMethodName());
Object returnObject = invocation.invoke(); //original method invocation.
return returnObject;
}
}
}
公共类代理示例{
公共静态void main(字符串[]args){
SomeImpl proxy=proxy.intercept(new SomeImpl(),new MyInterceptor());
log(“你好世界”);
//输出:
//SomeImpl.log
//你好,世界
}
公共静态类SomeImpl{
公共无效日志(字符串日志){
系统输出打印项次(日志);
}
}
公共静态类MyInterceptor实现拦截器{
@凌驾
公共对象拦截(调用)抛出可丢弃的{
System.out.println(invocation.getThis().getClass().getSuperclass().getSimpleName()+“+”+invocation.getMethodName());
Object returnObject=invocation.invoke();//原始方法调用。
返回对象;
}
}
}
如果您想做一些类似Java动态代理的事情,这可能是一种替代解决方案。它真的很轻,使用方便
Maven配置:
<dependency>
<groupId>com.ericsson.commonlibrary</groupId>
<artifactId>proxy</artifactId>
<version>1.2.0</version>
</dependency>
com.ericsson.commonlibrary
代理
1.2.0
满足您的请求的代码示例:
public class ProxyExample {
public static void main(String[] args) {
SomeImpl proxy = Proxy.intercept(new SomeImpl(), new MyInterceptor());
proxy.log("hello world");
//Output:
//SomeImpl.log
//hello world
}
public static class SomeImpl {
public void log(String log) {
System.out.println(log);
}
}
public static class MyInterceptor implements Interceptor {
@Override
public Object intercept(Invocation invocation) throws Throwable {
System.out.println(invocation.getThis().getClass().getSuperclass().getSimpleName() + "." + invocation.getMethodName());
Object returnObject = invocation.invoke(); //original method invocation.
return returnObject;
}
}
}
公共类代理示例{
公共静态void main(字符串[]args){
SomeImpl proxy=proxy.intercept(new SomeImpl(),new MyInterceptor());
log(“你好世界”);
//输出:
//SomeImpl.log
//你好,世界
}
公共静态类SomeImpl{
公共无效日志(字符串日志){
系统输出打印项次(日志);
}
}
公共静态类MyInterceptor实现拦截器{
@凌驾
公共对象拦截(调用)抛出可丢弃的{
System.out.println(invocation.getThis().getClass().getSuperclass().getSimpleName()+“+”+invocation.getMethodName());
Object returnObject=invocation.invoke();//原始方法调用。
返回对象;
}
}
}
为了扩大宁使用代理的建议, 您可以简单地使用oneliner:
InputStream serverInputStream = Proxy.addTimerToMethods(this.serverProcess.getInputStream());
serverInputStream.anymethodreally();
// any usage will now be printed to console with parameters+ performance data
使用新的Java 8+API对Ning的代理建议进行了更清晰的重写:
InputStream serverInputStream = with(this.serverProcess.getInputStream())
.interceptAll(i -> {
Object result = i.invoke();
System.out.println("after method: " + i.getMethodName() + " param: " + i.getParameter0());
return result;
}).get();
serverInputStream.anymethodreally();
// any usage will now be printed to console(or whatever you decide to do!)
使用代理而不是AspectJ的绝对主要好处是不需要学习一些自定义编译或语言。
代理基本上是一个更轻量级、更易于使用的解决方案(当然,它也有局限性)
和普通的decorator/interceptor/proxy类相比,使用代理当然不需要创建一个实现每个方法的新类。您也不必为每一个额外的类实现一个新的decorator/interceptor/proxy类
Proxy基本上允许您创建一个可以应用于任何类的通用方法拦截器。为了扩展Ning使用Proxy的建议, 您可以简单地使用oneliner:
InputStream serverInputStream = Proxy.addTimerToMethods(this.serverProcess.getInputStream());
serverInputStream.anymethodreally();
// any usage will now be printed to console with parameters+ performance data
使用新的Java 8+API对Ning的代理建议进行了更清晰的重写:
InputStream serverInputStream = with(this.serverProcess.getInputStream())
.interceptAll(i -> {
Object result = i.invoke();
System.out.println("after method: " + i.getMethodName() + " param: " + i.getParameter0());
return result;
}).get();
serverInputStream.anymethodreally();
// any usage will now be printed to console(or whatever you decide to do!)
使用代理而不是AspectJ的绝对主要好处是不需要学习一些自定义编译或语言。
代理基本上是一个更轻量级、更易于使用的解决方案(当然,它也有局限性)
和普通的decorator/interceptor/proxy类相比,使用proxy当然不需要创建一个