[SpringBoot Application] SpringBoot uses Aspect AOP to obtain method parameters based on annotations

[SpringBoot Application] SpringBoot uses Aspect AOP to obtain method parameters based on annotations

Requirements: The log content that needs to be saved is in the parameters of the method, and the type objects of the method parameters are different, and the attribute names of the objects are different.

[SpringBoot Application] SpringBoot uses Aspect AOP annotations to implement log management (enhanced version).
This article has given a solution. But if the parameters of the methods are different, the converter class will explode.
insert image description here
Solution: Realize dynamic acquisition of method parameters through reflection technology
1. Add field target attribute field in @LogPro annotation

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

    String desc() default "";

    String[] field() default "";

}

2. LogAspectPro aspect enhancement

@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;
    }

}

Problem: The problem of getting arg0 after getName of Parameter in Java reflection
insert image description here
. Solution:

<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>

Guess you like

Origin blog.csdn.net/qq_45297578/article/details/129958885