我正在尝试执行SOAPMessage的日志记录。这个对象包含包装类和JAXBElements,我正在执行如下操作
@Before("soapRequest()")
public void logBefore(JoinPoint joinPoint) {
Object[] signatureArgs = joinPoint.getArgs();
System.out.println("\n\n\n");
for (Object signatureArg : signatureArgs) {
StringBuilder sb = new StringBuilder();
try {
Field[] aClassFields = signatureArg.getClass().getDeclaredFields();
sb.append(signatureArg.getClass().getSimpleName() + " [ ");
for (Field f : aClassFields) {
f.setAccessible(true);
String fName = f.getName();
String value = "";
if(f.get(signatureArg) instanceof JAXBElement) {
log.info("is instance of");
JAXBElement val = (JAXBElement) f.get(signatureArg);
log.info(val.toString());
value = val.getValue().toString();
} else {
value = f.get(signatureArg).toString();
}
sb.append("(" + f.getType() + ") " + fName + " = " + value + ", ");
}
sb.append("]");
} catch (Exception e) {
e.printStackTrace();
}
System.out.println(sb.toString());
}
}然而,这一行抛出NPE:
if(f.get(signatureArg) instanceof JAXBElement) {
log.info("is instance of");
JAXBElement val = (JAXBElement) f.get(signatureArg);
log.info(val.toString());
value = val.getValue().toString();
}如何检查字段是否是JAXBElement的实例并从中提取值?
发布于 2020-03-31 04:22:05
实际上,我认为您的NPE发生在这一行代码的then块中:
value = f.get(signatureArg).toString();如果字段值为null,则会发生这种情况,因为在null上不能调用toString()。顺便说一句,这应该发生在任何null字段中,而不仅仅是JAXBElement字段。您不需要toString(),您只需删除它,因为当您打印任何对象时,它将在适用的情况下自动使用它的toString()表示。
在我看来,您的代码也比必需的要复杂得多,对于一些重构和重命名变量,then块根本就不再必要了。下面是我在普通Java + AspectJ (没有Spring)中为您提供的AspectJ:
package de.scrum_master.app;
import javax.xml.bind.JAXBElement;
public class Container {
private String name;
private JAXBElement jaxbElement;
public Container(String name, JAXBElement jaxbElement) {
this.name = name;
this.jaxbElement = jaxbElement;
}
}package de.scrum_master.app;
import javax.xml.bind.JAXBElement;
import javax.xml.namespace.QName;
public class Application {
public void doSomething(int number, String text, Container myContainer) {}
public static void main(String[] args) {
Application application = new Application();
application.doSomething(11, "foo", new Container("bar", new JAXBElement(new QName("local"), String.class, "dummy")));
application.doSomething(11, "foo", new Container("bar", null));
}
}package de.scrum_master.aspect;
import java.lang.reflect.Field;
import javax.xml.bind.JAXBElement;
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 MyAspect {
@Pointcut("execution(* doSomething(..))")
private void soapRequest() {}
@Before("soapRequest()")
public void logBefore(JoinPoint joinPoint) {
System.out.println(joinPoint);
for (Object methodArg : joinPoint.getArgs()) {
StringBuilder sb = new StringBuilder();
try {
sb.append(methodArg.getClass().getSimpleName() + " [ ");
for (Field field : methodArg.getClass().getDeclaredFields()) {
field.setAccessible(true);
String fieldName = field.getName();
Object value = field.get(methodArg);
if (value instanceof JAXBElement) {
System.out.println(" -> is instance of");
JAXBElement jaxbElement = (JAXBElement) value;
System.out.println(" -> " + jaxbElement);
value = jaxbElement.getValue();
}
// Un-comment this in order to see the NPE
//else {
// value = field.get(methodArg).toString();
//}
sb.append("(" + field.getType() + ") " + fieldName + " = " + value + ", ");
}
sb.append("]");
} catch (Exception e) {
e.printStackTrace();
}
System.out.println(" " + sb);
}
}
}控制台日志如下所示:
execution(void de.scrum_master.app.Application.doSomething(int, String, Container))
Integer [ (int) MIN_VALUE = -2147483648, (int) MAX_VALUE = 2147483647, (class java.lang.Class) TYPE = int, (class [C) digits = [C@8efb846, (class [C) DigitTens = [C@2a84aee7, (class [C) DigitOnes = [C@a09ee92, (class [I) sizeTable = [I@30f39991, (int) value = 11, (int) SIZE = 32, (int) BYTES = 4, (long) serialVersionUID = 1360826667806852920, ]
String [ (class [C) value = [C@4a574795, (int) hash = 0, (long) serialVersionUID = -6849794470754667710, (class [Ljava.io.ObjectStreamField;) serialPersistentFields = [Ljava.io.ObjectStreamField;@f6f4d33, (interface java.util.Comparator) CASE_INSENSITIVE_ORDER = java.lang.String$CaseInsensitiveComparator@23fc625e, ]
-> is instance of
-> javax.xml.bind.JAXBElement@4f023edb
Container [ (class java.lang.String) name = bar, (class javax.xml.bind.JAXBElement) jaxbElement = dummy, ]
execution(void de.scrum_master.app.Application.doSomething(int, String, Container))
Integer [ (int) MIN_VALUE = -2147483648, (int) MAX_VALUE = 2147483647, (class java.lang.Class) TYPE = int, (class [C) digits = [C@8efb846, (class [C) DigitTens = [C@2a84aee7, (class [C) DigitOnes = [C@a09ee92, (class [I) sizeTable = [I@30f39991, (int) value = 11, (int) SIZE = 32, (int) BYTES = 4, (long) serialVersionUID = 1360826667806852920, ]
String [ (class [C) value = [C@4a574795, (int) hash = 0, (long) serialVersionUID = -6849794470754667710, (class [Ljava.io.ObjectStreamField;) serialPersistentFields = [Ljava.io.ObjectStreamField;@f6f4d33, (interface java.util.Comparator) CASE_INSENSITIVE_ORDER = java.lang.String$CaseInsensitiveComparator@23fc625e, ]
Container [ (class java.lang.String) name = bar, (class javax.xml.bind.JAXBElement) jaxbElement = null, ]看见?你的错误已经消失了。注释else块以查看它的重新出现,然后从行中删除.toString(),它就会再次消失。也许它能帮助你更好地理解你的错误。
顺便说一下,我觉得日志输出看起来有点难看。您还注意到您也打印了静态字段吗?你应该把它们过滤掉。但是我不想修改你的代码,因为我仍然希望你能识别它。
您的方面的简短版本不需要为JAXBElement进行额外的调试日志记录,也不需要使用try - catch,而是声明了一个异常:
package de.scrum_master.aspect;
import java.lang.reflect.Field;
import javax.xml.bind.JAXBElement;
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 MyAspect {
@Pointcut("execution(* doSomething(..))")
private void soapRequest() {}
@Before("soapRequest()")
public void logBefore(JoinPoint joinPoint) throws Throwable {
System.out.println(joinPoint);
for (Object methodArg : joinPoint.getArgs()) {
StringBuilder sb = new StringBuilder();
sb.append(methodArg.getClass().getSimpleName() + " [ ");
for (Field field : methodArg.getClass().getDeclaredFields()) {
field.setAccessible(true);
String fieldName = field.getName();
Object value = field.get(methodArg);
if (value instanceof JAXBElement)
value = ((JAXBElement) value).getValue();
sb.append("(" + field.getType() + ") " + fieldName + " = " + value + ", ");
}
sb.append("]");
System.out.println(" " + sb);
}
}
}https://stackoverflow.com/questions/60936635
复制相似问题