Java切面编程 aop 自定义注解联合使用

Java切面编程 aop 自定义注解联合使用

示例需求:需要对某些接口统一增加数据上报 ,上报数据为部分入参字段,以及部分返参字段,

步骤一 : 定义自定义标签3个
标签1: 用于标识哪些接口需要上报
标签2: 用于标识入参对象哪些属性需要上报
标签3: 用于标识出参对象哪些属性需要上报

步骤二 : 定义一个切面拦截标签1标示的接口通过反射获取对于字段的值上报信息

标签1示例代码:

import java.lang.annotation.*;

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

标签2示例代码:


import java.lang.annotation.*;
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface DoubleActiveParamKey {
    
    
    // 例如:token映射到商户号,则token为key,商户号为value    dto.setValue(${value});
    String[] keys() default {
    
    };
}

注解2的使用方式

@Getter
@Setter
@ToString(callSuper = true)
@DoubleActiveParamKey(provider = "example-hessian", keyPrefix = "refundOrder", keys = {
    
    "orderId", "token","refundOrderId"})
public class RefundRequestDTO extends BaseRequestDTO implements Serializable {
    
    
  /**
     * 原交易订单号
     */
    @NotBlank(message = ErrorMessageConstant.REQUEST_ID_BLANK)
    @Size(max = 64, message = ErrorMessageConstant.REQUEST_ID_WRONG)
    private String orderId;

    /**
     * 退款订单号
     */
    @Size(max = 64, message = ErrorMessageConstant.REFUND_REQUEST_ID_IS_WRONG)
    @NotBlank(message = ErrorMessageConstant.REFUND_REQUEST_ID_IS_BLANK)
    private String refundOrderId;
    ...........
    

}

标签3示例代码:

 import java.lang.annotation.*;

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface DoubleActiveParamValue {
    
    
    String[] values() default {
    
    };

    String provider() default "example-hessian";

    String keyPrefix() default "examplePrefix";

}
@Getter
@Setter
@ToString(callSuper = true)
@DoubleActiveParamValue(values = {
    
    "uniqueRefundNo", "refundOrderId"})
public class RefundResponseDTO extends BaseResponseDTO {
    
    
    private static final long serialVersionUID = 1L;

    private String refundOrderId;

    private String uniqueRefundNo;

    private BigDecimal refundAmount;
    ......
    

步骤二 : 定义一个切面拦截标签1标示的接口通过反射获取对于字段的值上报信息

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;

import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;

@Aspect
@Component
public class DoubleActiveProxy {
    
    
    private Logger logger = LoggerFactory.getLogger(DoubleActiveProxy.class);

    private static final UnifierTradeClient unifierTradeClient = new UnifierTradeClient();

    /**
     * DoubleActiveProxy
     *
     * @param pjp
     * @throws Throwable
     */
    @Around("@annotation(DoubleActiveMarkerMethod)")
    public void doAroundDoubleActiveData(ProceedingJoinPoint pjp) throws Throwable {
    
    

        final List<MapperDto> mapperDtoList = new LinkedList<MapperDto>();
        try {
    
    
            final Iterator<Object> var1 = Arrays.stream(pjp.getArgs()).iterator();

            while (var1.hasNext()) {
    
    
                final Object pjpArg = var1.next();
                Class<? extends Object> pjpArgClazz = pjpArg.getClass();

                if (pjpArgClazz.isAnnotationPresent(DoubleActiveParamKey.class)) {
    
    
                    DoubleActiveParamKey doubleActiveParamKey = (DoubleActiveParamKey)
                            pjpArgClazz.getAnnotation(DoubleActiveParamKey.class);
                    //
                    final String[] doubleActiveKeys = doubleActiveParamKey.keys();

                    final Iterator<String> var2 = Arrays.stream(doubleActiveKeys).iterator();
                    while (var2.hasNext()) {
    
    
                        String[] doubleActiveKey = {
    
    var2.next()};

                        String clazzFieldValue = this.getClazzFieldValue(pjpArgClazz, doubleActiveKey, pjpArg);
                        if (null != clazzFieldValue) {
    
    
                            MapperDto mapperDto = new MapperDto();
                            // set provider and KeyPrefix
                            mapperDto.setKeyPrefix(doubleActiveParamKey.keyPrefix());
                            mapperDto.setProvider(doubleActiveParamKey.provider());

                            //set everyone active key
                            mapperDto.setKey(StringUtils.defaultIfNull(clazzFieldValue));
                            mapperDtoList.add(mapperDto);
                        }
                    }
                }
            }
            //continue handle process
            Object proceed = pjp.proceed();

            final Class<? extends Object> clazz = proceed.getClass();
            String doubleActiveValue = null;
            if (clazz.isAnnotationPresent(DoubleActiveParamValue.class)) {
    
    
                DoubleActiveParamValue doubleActiveParamValue = (DoubleActiveParamValue)
                        clazz.getAnnotation(DoubleActiveParamValue.class);
                // get field value
                doubleActiveValue = getClazzFieldValue(clazz, doubleActiveParamValue.values(), proceed);
            }

            //set everyone active values
            final Iterator<MapperDto> var4 = mapperDtoList.iterator();
            while (null != doubleActiveValue && var4.hasNext()) {
    
    
                var4.next().setValue(StringUtils.defaultIfNull(doubleActiveValue));
            }
            ///asynchronous batch report data
            asyncBatchReportTradeUnifier(mapperDtoList);

        } catch (Throwable var5) {
    
    
            logger.error("double active interception failed!", var5);
            throw var5;
        }
    }

    /**
     * 异步上传数据
     * @param mapperDtoList
     */
    private void asyncBatchReportTradeUnifier(final List<MapperDto> mapperDtoList) {
    
    
        try {
    
    
            AsyncThreadPoolUtil.getThreadPool().execute(
                    new AbstractAsyncTask("batchReportSync") {
    
    
                        @Override
                        public void execute() {
    
    
                            try {
    
    
                                boolean batchReportSync = unifierTradeClient.batchReportSync(mapperDtoList);
                                if (!batchReportSync) {
    
    
                                    logger.warn("batchReportSync report data! batchReportSync:{}, mapperDtoList:{}", batchReportSync, mapperDtoList);
                                }
                            } catch (Throwable var2) {
    
    
                                logger.error("batchReportSync exception! mapperDtoList:{}" + mapperDtoList + " ", var2);
                            }
                        }
                    }
            );
        } catch (Throwable var3) {
    
    
            logger.error("batchReportSync threadPoll run exception! mapperDtoList:{}" + mapperDtoList + " ", var3);
        }
    }


    /**通过反射递归获取属性的值
     * @param clazz
     * @param doubleActiveParamKeys
     * @param pjpArg
     * @return
     * @throws Throwable
     */
    private String getClazzFieldValue(final Class<?> clazz, final String[] doubleActiveParamKeys,
                                      final Object pjpArg) throws Throwable {
    
    
        Class<?> clazzVar = clazz;
        Boolean isFirstKey = Boolean.TRUE;
        StringBuffer sb = new StringBuffer();

        do {
    
    
            isFirstKey = getThisClazzFieldValue(isFirstKey, sb, clazzVar, doubleActiveParamKeys, pjpArg);
            // find parent class
            clazzVar = clazzVar.getSuperclass();
        }
        while (null != clazzVar);

        // not found field ,
        if (isFirstKey) {
    
    
            return null;
        }

        return sb.toString();
    }

    /**
     * 获取属性值
     * @param isFirstKey
     * @param sb
     * @param clazz
     * @param doubleActiveParamKeys
     * @param pjpArg
     * @return
     * @throws Throwable
     */
    private Boolean getThisClazzFieldValue(Boolean isFirstKey, StringBuffer sb, final Class<?> clazz,
                                           final String[] doubleActiveParamKeys, final Object pjpArg) throws Throwable {
    
    
        Field[] declaredFields = clazz.getDeclaredFields();
        //get keyValue by field
        if (null != doubleActiveParamKeys && doubleActiveParamKeys.length > 0) {
    
    
            Iterator<String> var1 = Arrays.stream(doubleActiveParamKeys).iterator();
            while (var1.hasNext()) {
    
    
                String doubleActiveParamKey = var1.next();
                Iterator<Field> var2 = Arrays.stream(declaredFields).iterator();
                while (var2.hasNext()) {
    
    
                    Field field = var2.next();
                    //get one field key
                    if (StringUtils.equals(field.getName(), doubleActiveParamKey)) {
    
    
                        field.setAccessible(Boolean.TRUE);
                        sb.append(isFirstKey ? field.get(pjpArg) : (":" + field.get(pjpArg)));
                        isFirstKey = Boolean.FALSE;
                    }
                }
            }
        }
        return isFirstKey;
    }

    /**
     * 需上报的数据dto
     */
    public class MapperDto {
    
    
        String provider;

        String keyPrefix;

        String key;

        String value;

        public String getProvider() {
    
    
            return provider;
        }

        public void setProvider(String provider) {
    
    
            this.provider = provider;
        }

        public String getKeyPrefix() {
    
    
            return keyPrefix;
        }

        public void setKeyPrefix(String keyPrefix) {
    
    
            this.keyPrefix = keyPrefix;
        }

        public String getKey() {
    
    
            return key;
        }

        public void setKey(String key) {
    
    
            this.key = key;
        }

        public String getValue() {
    
    
            return value;
        }

        public void setValue(String value) {
    
    
            this.value = value;
        }
    }
}

猜你喜欢

转载自blog.csdn.net/qq_28344049/article/details/110092596