[英]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.