借助spring的SpEL和AOP面向注解的切面编程

1:第一次写博客,如果有问题请多多包含,
  先说下思路: 
  1.1 :先建立一个注解类,这个是使用在方法上的。
  1.2 :再建立一个专门做spring的bean的方法中传参解析的EL类。
  1.3 : 这里我们还需要一个处理spring的AOP的类,针对注解做切面编程 , 这个类可以做公共日志打印
  
接下来就直接上代码了,下面的类是根据上面的思路来的。

1:注解类:用来放在方法前面,做切面使用
/**
 * 类描述:
 *    复核的判断验证
 * @Author qq: 841495046
 * @date: 2018/12/22
 * @Version:1.1.0
 */
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE,ElementType.METHOD})
public @interface VerificationMethod {

  /**
   * EL
   */
  String entryKey();
  /**
   * 方法名
   * 多个方法请使用逗号隔开
   * @return
   */
  String method();

  /**
   * 方法的描述
   * @return
   */
  String describe() default "";

  /**
   * 是否需要日志打印
   */
  boolean needLog() default false;
}
获取spring的EL的值: 通过spring来获取方法中入参的实体对象值
/**
 * 类描述:  获取spring的EL的值
 *
 * @Author qq:  841495046
 * @date: 2018/12/22
 * @Version:1.1.0
 */
public final class SpelEl {

  private static ExpressionParser parser = new SpelExpressionParser();

  /**
   * @param key el表达式字符串,占位符以#开头
   * @param paramsNames 形参名称,可以理解为占位符名称
   * @param args 参数值,可以理解为占位符真实的值
   * @功能描述: 返回el表达式经过参数替换后的字符串值
   * @return: String
   * @Author qq: 841495046
   * @date: 2018/12/22 10:09
   * @Version:1.1.0
   */
  public static String getEntityKey(String key, String[] paramsNames, Object[] args) {
    Expression exp = parser.parseExpression(key);
    //初始化赋值上下文
    EvaluationContext context = new StandardEvaluationContext();
    if (args.length <= 0) {
      return null;
    }
    //将形参和形参值以配对的方式配置到赋值上下文中
    for (int i = 0; i < args.length; i++) {
      context.setVariable(paramsNames[i], args[i]);
    }
    //根据赋值上下文运算el表达式

    return exp.getValue(context, String.class);
  }


  /**
   * @param paramsNames : 形参名称,可以理解为占位符名称
   * @功能描述:
   * @return: 获取对象
   
   * @date: 2018/12/22 11:28
   * @Version:1.1.0
   */
  public static Object getKeyEntity(String key, String[] paramsNames, Object[] args) {
    Expression exp = parser.parseExpression(key);
    EvaluationContext context = new StandardEvaluationContext();
    if (args.length <= 0) {
      return null;
    }
    for (int i = 0; i < args.length; i++) {
      context.setVariable(paramsNames[i], args[i]);
    }
    return exp.getValue(context, Object.class);
  }


}

 

3:spring的AOP处理类

@Component
@Aspect
public class MethodAspect {

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


  /**
   * @功能描述: Method method = ((MethodSignature)pjp.getSignature()).getMethod(); VerificationMethod
   * annotation = method.getAnnotation(VerificationMethod.class);
   * @return: Object
   
   * @date: 2018/12/22 11:21
   * @Version:1.1.0
   */
  @Around("@annotation(vfm)")
  public Object doMethodValidate(ProceedingJoinPoint pjp, VerificationMethod vfm) throws Throwable {

    // 方法的入参
    Object entryObject = getKeyEntity(pjp, vfm.entryKey());
    String methodName = vfm.method();
    String describe = vfm.describe();
    boolean needLog = vfm.needLog();
    OmPdaBoxDto omPdaBoxDto = null;
    if (needLog) {
      LOGGER.info("方法名[{}],方法描述[{}]", methodName, describe);
    }
    String[] methods = methodName.split(",");
    //有值
    if (methods.length > 0) {
      omPdaBoxDto = BeanUtils.toBean(entryObject, OmPdaBoxDto.class);
      omPdaBoxDto.setLocno(OutputContext.getLocno());
      omPdaBoxDto.setUserId(OutputContext.getCurrentSimpleUserInfo().getLoginName());
      RecheckValidateMethod rvm = GetObjectBean.getRecheckValidateMethod();
      int count = 1;
      for (String method : methods) {
        LOGGER.info("------------------转换方法:MethodAspect[{}]------------", method);
        ResultData<String> ob = (ResultData<String>) executionParameterMethod("validate" + method,
            rvm, new Object[]{omPdaBoxDto});
        if (ob != null && ob.getCode() != 0) {
          return ob;
        }
        if (ob != null && count == 1 && StringUtils.isNotBlank(ob.getData())) {
          omPdaBoxDto.setDate(ob.getData());
        }
        count++;

        if (ob != null && ob.getCode() == 0 && ob.getSubCode() != null) {
          return ob;
        }


      }
    }
    Object ret = null;
    try {
      ret = pjp.proceed(new Object[]{omPdaBoxDto});
    } catch (Exception e) {
      LOGGER.error("MethodAspect方法异常" + describe + "[{}]", e.getMessage());
      e.printStackTrace();
      throw new BaseException("校验失败");
    }

    return ret;
  }


  /**
   * @param pjp :注入对象
   * @功能描述 : 获取单个字符
   * @return:
   
   * @date: 2018/12/22 11:36
   * @Version:1.1.0
   */

  private String getKeyStr(ProceedingJoinPoint pjp, String key) {
    Method method = ((MethodSignature) pjp.getSignature()).getMethod();
    String[] parameterNames = new LocalVariableTableParameterNameDiscoverer()
        .getParameterNames(method);
    return SpelEl.getEntityKey(key, parameterNames, pjp.getArgs());
  }


  /**
   * @param pjp :注入对象
   * @功能描述: 获取对象
   * @return:
  
   * @date: 2018/12/22 11:35
   * @Version:1.1.0
   */

  private Object getKeyEntity(ProceedingJoinPoint pjp, String key) {
    Method method = ((MethodSignature) pjp.getSignature()).getMethod();
    String[] parameterNames = new LocalVariableTableParameterNameDiscoverer()
        .getParameterNames(method);
    return SpelEl.getKeyEntity(key, parameterNames, pjp.getArgs());
  }


  /**
   * @功能描述: 根据属性名称获取属性的对应值
   * @param: fieldName-属性名称
   * @param: o-类对象
   * @return: Object
  
   * @date: 2018/12/18 10:41
   * @Version:1.1.0
   */
  private static Object executionNoParameterMethod(String fieldName, Object o) {
    try {
      Method method = o.getClass().getMethod(fieldName, new Class[]{});
      Object value = method.invoke(o, new Object[]{});
      return value;
    } catch (Exception e) {
      LOGGER.info("executionNoParameterMethod执行异常[{}]", e.getMessage());
      e.printStackTrace();
      return null;
    }
  }

  /**
   * @param methodName 方法名称
   * @param obj 调用此方法的对象
   * @param args 调用的这个方法的参数参数列表
   * @功能描述: 执行带参数的方法
   * @return: Object
   
   * @date: 2018/12/22 14:15
   * @Version:1.1.0
   */

  public static Object executionParameterMethod(String methodName, Object obj, Object[] args) {
    Class c[] = null;
    //1.参数存在
    if (args != null) {
      int len = args.length;
      c = new Class[len];
      for (int i = 0; i < len; ++i) {
        c[i] = args[i].getClass();
      }
    }
    try {
      Method method = obj.getClass().getDeclaredMethod(methodName, c);
      LOGGER.error("----------反射调用:方法名称-----------------:[{}]", method.getName());
      try {
        Object value = method.invoke(obj, args);
        LOGGER.error("----------反射调用:方法名称-返回结果----------------:[{}]", value.toString());
        return value;
      } catch (Exception ex) {
        ex.printStackTrace();
        LOGGER.error("反射调用:方法名称:[{}],Exception ex 错误码:[{}]", MethodAspect.class.getName(),
            ex.getMessage());
        return null;
      }
    } catch (Exception ex) {
      ex.printStackTrace();
      LOGGER.error("反射调用:obj.getClass().getDeclaredMethod(methodName, c)方法名称:[{}]",
          MethodAspect.class.getName());
      return null;
    }
  }

}

 

 

使用案列方法:  面向注解的切面编码

MethodEnum.RECHECK_BOX_NO_ONE:对象的是指定类里面的方法名称
#omPdaBoxDto:spring的service类中方法的入参属性名
@VerificationMethod(method = MethodEnum.RECHECK_BOX_NO_ONE, entryKey = "#omPdaBoxDto")
public ResultData<OmPdaBoxVo> selectOmPdaBoxVo(OmPdaBoxDto omPdaBoxDto) {
  return ResultData.ok();
}

 

 

如有疑问加QQ:841495046 一起探讨,一起成长

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值