繁体   English   中英

使用 @Aspect 类型 ZA2F2ED4F8EBC04ABBB4C21A2D9 中的 java 反射访问用户定义的 object state

[英]Access user-defined object state using java reflection in @Aspect type class

我有一个 class A,它声明了一个 static 记录器实例,然后在 class 的方法中使用。

class A {
  static Log log = LogFactory.getLog(A.class);
   person p = new Person();
   public void methodA(){
     // log.info("logging using apache commons logger");
      }
  }

我还有另一个 class B,它是 @Aspect 类型。 它的方法可以基于A的方法的执行而触发。

@Aspect
 class B{

  @Before(--execution of methodA() pointcut expression--)
   public void methodB(JoinPoint jp){
   // How to get the class A's logger instance to continue logging from same logger instance. As it will print class name   A in logs
        }

  }

我想使用 class A 中使用的记录器实例来记录一些消息。

如何通过反射从joinPoint 中获取对象的state 方面class。

我没有使用 spring 框架,尝试使用 aspectjrt aspectweaver jars

您可以使用jp.getTarget()获取非静态方法的目标实例,也可以简单地将target(targetObject)绑定到建议方法参数。 我向你展示的是后者。 这是我的MCVE

Log4J配置:

log4j.rootLogger=DEBUG, consoleAppender
log4j.appender.consoleAppender=org.apache.log4j.ConsoleAppender
log4j.appender.consoleAppender.layout=org.apache.log4j.PatternLayout
log4j.appender.consoleAppender.layout.ConversionPattern=[%t] %-5p %c %x - %m%n

助手 class:

package de.scrum_master.app;

public class Person {}

驱动应用 class:

package de.scrum_master.app;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

public class Application {
  private static Log log = LogFactory.getLog(Application.class);
  private Person p = new Person();

  public void methodA() {}

  public static void main(String[] args) {
    Application application = new Application();
    application.methodA();
  }
}

方面:

package de.scrum_master.aspect;

import java.lang.reflect.Modifier;
import java.util.Arrays;

import org.apache.commons.logging.Log;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;

@Aspect
public class MyAspect {
  @Before("execution(* methodA()) && target(targetObject)")
  public void logMethodExecution(JoinPoint jp, Object targetObject) {
    // Filter for static logger, make it accessible and use it for logging 
    Arrays.stream(targetObject.getClass().getDeclaredFields())
      .filter(field -> field.getType().equals(Log.class) && Modifier.isStatic(field.getModifiers()))
      .forEach(field -> {
        try {
          field.setAccessible(true);
          ((Log) field.get(null)).info(jp + " -> logging using apache commons logger");
        } catch (IllegalArgumentException | IllegalAccessException e) {
          e.printStackTrace();
        }
      });
  }
}

控制台日志:

[main] INFO  de.scrum_master.app.Application  - execution(void de.scrum_master.app.Application.methodA()) -> logging using apache commons logger

如果方面和目标 class 不在同一个模块中,这种反射的东西非常难看,并且在没有配置预防措施的 JMS 风格的模块化应用程序中可能无法按照您希望的方式工作。 至少,您可以公开您的记录器以避免使用field.setAccessible(true)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM