Bootstrap

【SpringBoot应用篇】【AOP+注解】SpringBoot使用Aspect AOP基于注解获取方法形参

【SpringBoot应用篇】【AOP+注解】SpringBoot使用Aspect AOP基于注解获取方法形参

需求: 需要保存的日志内容在方法的参数中,并且方法参数的类型对象不一样,且对象的属性名称不一样。

【SpringBoot应用篇】SpringBoot使用Aspect AOP注解实现日志管理(增强版)
这一篇文章已经给出了解决方法。但是如果方法的参数不同,会出来转换器类爆炸的情况。
在这里插入图片描述
解决思路: 通过反射技术实现动态获取方法参数
1、@LogPro注解中添加field目标属性字段

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface LogPro {

    String desc() default "";

    String[] field() default "";

}

2、LogAspectPro切面增强

@Component
@Aspect
public class LogAspectPro {

    private static final Logger LOGGER = LoggerFactory.getLogger(LogAspectPro.class);

    @Pointcut("@annotation(cn.zysheep.anno.LogPro)")
    public void pointcut(){}

    @Before("pointcut()")
    public void before(JoinPoint joinPoint) {
        MethodSignature signature = (MethodSignature)joinPoint.getSignature();
        Method method = signature.getMethod();

        Map<String, Object> paramMap = new HashMap(16);
        Parameter[] parameters = method.getParameters();
        Object[] parameterValues = joinPoint.getArgs();
        if (parameters != null && parameters.length > 0) {
            for (int i = 0; i < parameters.length; ++i) {
                Map<String, Object> subPlaceholder = this.getAttrs(parameters[i], parameterValues[i]);
                paramMap.putAll(subPlaceholder);
            }
        }

        LogPro logPro = method.getAnnotation(LogPro.class);
        if (logPro != null) {
            String[] field = logPro.field();
            String str = (String)paramMap.get(field[0]);
            LOGGER.info("str:{}", str);
        }
    }

    /**
     * 获取参数
     * @param parameter
     * @param value
     *
     * @return
     */
    private Map<String, Object> getAttrs(Parameter parameter, Object value) {
        Map<String, Object> map = new HashMap<>();
        if (parameter.getType().getClassLoader() == null) {
            map = this.getJdkTypeAttrs(parameter, value);
        } else {
            map = this.getCustomObjAttrs(value);
        }
        return map;

    }

    /**
     * 获取jdk自带类型的参数
     * 8种基本数据类型、List、Map
     * @param parameter
     * @param value
     *
     * @return
     */
    private Map<String, Object> getJdkTypeAttrs(Parameter parameter, Object value) {
        Map<String, Object> map = new HashMap<>();
        if (value instanceof Integer
                || value instanceof Long
                || value instanceof Short
                || value instanceof Float
                || value instanceof Byte
                || value instanceof String
                || value instanceof Boolean
                || value instanceof Double) {
            map.put(parameter.getName(), value);
            return map;
        }
        if (value instanceof List) {
            map.putAll(this.getCustomObjAttrs(((List) value).get(0)));
            return map;
        }
        if (value instanceof Map) {
            map.putAll((Map<? extends String, ?>) value);
            return map;
        }
        LOGGER.error("参数类型不支持 type:{}", parameter.getType().getName());
        return map;
    }

    /**
     * 获取自定义对象类型的参数
     *
     * @param object
     * @return
     */
    private Map<String, Object> getCustomObjAttrs(Object object) {
        Map<String, Object> map = new HashMap(16);
        Class<?> clazz = object.getClass();
        Field[] fields = clazz.getDeclaredFields();
        if (fields != null && fields.length != 0) {
            int length = fields.length;
            for (int i = 0; i < length; ++i) {
                Field field = fields[i];
                try {
                    field.setAccessible(true);
                    Object value = field.get(object);
                    if (value != null) {
                        map.put(field.getName(), value);
                    }
                } catch (Exception e) {
                    LOGGER.warn("读取属性失败", e);
                }
            }
            return map;
        } else {
            return map;
        }
    }


    /**
     * 判断一个类是JAVA类型还是用户定义类型
     * @param clz
     * @return getClassLoader()为null是JAVA类型
     */
    private static boolean isJavaClass(Class<?> clz) {
        return clz != null && clz.getClassLoader() == null;
    }

}

问题:Java反射中Parameter的getName后得到arg0的问题
在这里插入图片描述
解决方法:

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <configuration>
                <source>${java.version}</source>
                <target>${java.version}</target>
                <compilerArgs>
                    <arg>-parameters</arg>
                </compilerArgs>
                <encoding>${project.build.sourceEncoding}</encoding>
            </configuration>
        </plugin>
    </plugins>
</build>
;