• 【转】通过BeanNameAutoProxyCreator改变臃肿代码


    https://www.cnblogs.com/zdd-java/p/7861824.html

      前言:

                  最近接手了一个项目,大概过了下需求,然后打开项目准备开搞的时候发现一个问题,这个项目是提供rest服务的一个web项目,其中很多旧系统由于还没改成微服务,所以只能通过HttpClient发起调用。之前的开发人员为了监控每个方法的执行时间,在方法开始和结束写了很多logger.info("耗时:"+time)这种代码。很显然这是不规范的,当项目里到处有这样的代码存在降低了代码的可读性,于是改造后如下:

      

       #创建一个方法拦截器:

    复制代码
    /**
     * 用来监控方法的执行时间-- 对应配置文件是spring-servlet.xml
     * PS:必须放到springmvc的配置文件里,放在spring父容器里面由于先初始化的是spring父容器上下文,先实例化的是除@Controller外的bean,所以无法生成代理。
     *
     * @author dada
     * @version $Id: MethodTimeAdvice.java, v 0.1
     * @date 2017年11月15日 09:47:23
     */
    public class MethodTimeAdvice implements MethodInterceptor {
    
        private final static Logger logger = Logger.getLogger("DAL-MONITOR");
    
        /**
         * @see org.aopalliance.intercept.MethodInterceptor#invoke(org.aopalliance.intercept.MethodInvocation)
         */
        public Object invoke(MethodInvocation invocation) throws Throwable {
            //用 commons-lang 提供的 StopWatch 计时,Spring 也提供了一个 StopWatch
            StopWatch clock = new StopWatch();
            clock.start(); //计时开始
            Object result = null;
            //监控的方法名
            String methodName = getRequestMappingName(invocation);
            if(null == methodName){
                methodName = invocation.getMethod().getDeclaringClass().getSimpleName();
            }
            try {
                //这个是我们监控的bean的执行并返回结果
                result = invocation.proceed();
            } catch (Throwable e) {
                //监控的类名
                String className = invocation.getMethod().getDeclaringClass().getSimpleName();
                //监控的参数
                Object[] objs = invocation.getArguments();
                logger.error("控制层执行异常,方法名:" + className + "参数: " + getString(objs), e);
                throw e;
            }
            clock.stop(); //计时结束
            if (logger.isInfoEnabled()) {
                logger.info("[  " + methodName + "  ] 执行时间:" + clock.getTime() + " ms ");
            }
            return result;
        }
    
        /**
         * 这个类主要是用于输出方法的参数
         *
         * @param objs
         * @return
         */
        @SuppressWarnings("unchecked")
        public String getString(Object[] objs) {
            StringBuffer stringBuffer = new StringBuffer();
            for (int i = 0, len = objs.length; i < len; i++) {
                if (objs[i] instanceof String) {
                    stringBuffer.append("String类型:" + objs[i].toString());
                } else if (objs[i] instanceof Map) {
                    HashMap<String, Object> hashMap = (HashMap<String, Object>) objs[i];
                    HashMap<String, Object> map = hashMap;
                    HashSet<String> set = (HashSet<String>) map.keySet();
                    stringBuffer.append("Map类型");
                    for (String str : set) {
                        stringBuffer.append(str + "=" + map.get(str));
                    }
                } else if (objs[i] instanceof Integer) {
                    stringBuffer.append("整数类型:");
                    stringBuffer.append(objs[i].toString());
                } else {
                    stringBuffer.append(objs[i].toString());
                }
            }
            return stringBuffer.toString();
        }
    
    
        public String getRequestMappingName(MethodInvocation invocation){
            Method method = invocation.getMethod();
            RequestMapping requestMapping = method.getAnnotation(RequestMapping.class);
            if(requestMapping!=null){
                return requestMapping.name();
            }
            return null;
        }
    }
    复制代码

      #配置 Spring BeanNameAutoProxyCreator, 用来拦截上面的 MethodTimeAdvice,切记必须放到spring-mvc.xml配置里,因为已经测试过如果放到spring的xml里面会导致扫描不到从而无法切面。

    复制代码
    <bean id="methodTimeAdvice" class="com.i2p.admin.interceptor.MethodTimeAdvice" />
    
        <!-- 根据 Bean 的名字自动实现代理拦截 -->
        <bean
                class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
            <property name="interceptorNames">
                <list>
                    <value>methodTimeAdvice</value>
                </list>
            </property>
            <property name="beanNames">
                <list>
                    <!-- 添加到其中的 Bean 自动就被代理拦截了(下面的是对应的bean的名称,那么当请求InnovatePartBorrowController任何一个方法都会执行MethodTimeAdvice里面的Invoke方法) -->
                    <value>innovatePartBorrowController</value>
                </list>
            </property>
        </bean>
    复制代码

     #其中上面的配置里innovatePartBorrowController就是需要被打印的类。

    总结:

       通过spring 代理,不仅减少了代码的copy工作,同时又方便管理;至于后续如果有新的类需要实现打印功能,我们只需要在spring-mvc.xml里配置好对应的bean就能实现日志的打印。

  • 相关阅读:
    查找代码行数和查看域名版本
    iOS10里的通知与推送
    计算有多少个岛屿
    java.lang.NoClassDefFoundError: Could not initialize class com.haoyao.shop.common.XXX
    Windows 版本Mongodb 启动
    安装第三方库 报错Python version 2.7 required, which was not found in the registry
    Python 爬虫 报错 403 HTTP Error 403: Forbidden
    廖雪峰 练习 把用户输入的不规范的英文名字,变为首字母大写,其他小写的规范名字
    利用Python 2.7打印杨辉三角
    MAVEN实战 读书笔记 第二章
  • 原文地址:https://www.cnblogs.com/exmyth/p/11094033.html
Copyright © 2020-2023  润新知