zoukankan      html  css  js  c++  java
  • 反射?切面?怎样对公共参数及行为进行封装

      现在都是微服务化访问,某系统访问另一系统时,总有一些公用参数需要处理,另外还需要对访问情况进行日志打印。
      调用的服务是dubbo服务,如何封装这一些公共参数而不是每次调用方法时都做反复的事呢?
    三个方法:
      1. 写一个公共方法,在调用rpc方法前和方法后,都进行调用;
        简单直接且易读,且想加就加更灵活。不好处就是每个地方都要重复写这两段公用代码,不简洁。
      2. 使用反射方法,进行调用dubbo方法,在调用前调用后,都进行参数组装,并将日志打印好。
        好处是每次只需调用一个反射封装方法,就能完成所有工作,简单实用。坏处是方法被反射调用后,不直观,无法使用ide的语法检查快速发现潜在问题。
      3. 使用切面进行设值处理。
        好处是代码无侵入,简洁明了。坏处是新来的同学不易理解一些运行原理,不能很好利用切面辅助,另外,切面规则需要保持一致,否则无法实现处理。
    来几个实现的例子吧!
    使用公共方法:

    // 公用封装参数方法,四处调用,当然这里是不完整的封装,可能还需要更复杂的代码侵入
        public static void wrapCommonField(Object param) {
            ThreadlocalVar session = ThreadlocalVar.getVar();
            if (null != param && (param instanceof BaseDTO)) {
                BaseDTO basePara = (BaseDTO) param;
                if (null != session) {
                    basePara.setIp(session.getIp());
                    if(session.getUserId() != null) {
                        basePara.setUserId(session.getUserId());
                    }
                }
            }
            // ...
        }
    // 调用,在调用service方法时,先鲁一段该调用代码
        public static void main(String[] args) {
            RpcServiceA serviceA = new RpcServiceA();
            Object param = ...;
            wrapCommonField(param);
            // ...
        }

    使用反射:

    // 公用反射方法
        public static <T> T callMethod(Object service, String mName, Object param) {
            ThreadlocalVar session = ThreadlocalVar.getVar();
            if (null != param && (param instanceof BaseDTO)) {
                BaseDTO basePara = (BaseDTO) param;
                if (null != session) {
                    basePara.setIp(session.getIp());
                    if(session.getUserId() != null) {
                        basePara.setUserId(session.getUserId());
                    }
                }
            }
            Class<?> rpcServiceClass = service.getClass();
            logger.info("call method:{},param:{}", mName, param);
            try {
                Method method = rpcServiceClass.getMethod(mName, new Class[] { param.getClass() });
                ResponseResult<T> re = (ResponseResult<T>) method.invoke(rpcService, new Object[] { param });
                logger.info("result:{}", re);
                if (null == re || !"1111".equals(re.getCode())) {
                    throw new RuntimeException(re.getCode(), re.getMsg());
                }
                return re.getData();
            } catch (NoSuchMethodException | InvocationTargetException e) {
                logger.error("exception:{}", e);
                throw e;
            } catch (SecurityException | IllegalAccessException | IllegalArgumentException e) {
                logger.error("exception:{}", e);
                throw e;
            }
        }
    // 调用
        public static void main(String[] args) {
            RpcServiceA serviceA = new RpcServiceA();
            Object param = ...;
            callMethod(serviceA, "giveMeFive", param);
            // ...
        }

    使用切面:

    // 完整切面类,独立
    @Order(1)
    @Component
    @Aspect
    public class SignLoginAop {
    
        private Logger logger = LoggerFactory.getLogger(getClass());
        
        public static final String CALLAPI_POINT = "execution(* com.xx.api.web.d.*.*(..))";
        
        @Around(CALLAPI_POINT)
        public Object validSign(ProceedingJoinPoint pjp) throws NoSuchMethodException, SecurityException, KydException {
            Object retVal = null;
            
            Object[] args = pjp.getArgs();
            Object param = (null != args && args.length > 0) ? args[0] : null;
            if (null != param && (param instanceof BaseDTO)) {
                BaseDTO basePara = (BaseDTO) param;
                ThreadlocalVar session = ThreadlocalVar.getSession();
                BaseDTO basePara = (BaseDTO) param;
                if (null != session) {
                    basePara.setIp(session.getIp());
                    if(session.getUserId() != null) {
                        basePara.setUserId(session.getUserId());
                    }
                }
            }
            Signature signature = pjp.getSignature();
            try {
                logger.info("call method {}, param:{}", signature, args);
                retVal = pjp.proceed(args);
                logger.info("end method {}, retVal:{}", signature, retVal);
            } catch (Exception e) {
                logger.error("发生了错误:", e);
                throw e;
            }
            //...
        }
    }
    // 使用,独立写业务

    性能对比!额,就不去收集对比数据了。第一个自然最快。第二、三个不相伯仲!

    封装是为了代码更简洁!哟豁。

  • 相关阅读:
    Python 机器学习实战 —— 监督学习(上)
    Python 基础教程 —— Pandas 库常用方法实例说明
    Python 基础教程 —— 网络爬虫入门篇
    2个周末,历时100+小时,YourBatman新版Blog正式上线
    玩转IDEA项目结构Project Structure,打Jar包、模块/依赖管理全搞定
    谁再把IDEA的Project比作Eclipse的Workspace,我就跟谁急
    IntelliJ IDEA 20周岁啦,为期2天的周年庆活动对开发者免费开放
    数字跳动 jqjs
    js多项筛选功能
    调用本地摄像头实现拍照拍照截取照片 jqjs 、 vue
  • 原文地址:https://www.cnblogs.com/yougewe/p/9449091.html
Copyright © 2011-2022 走看看