【原】經過BeanNameAutoProxyCreator改變臃腫代碼

  前言:

              最近接手了一個項目,大概過了下需求,而後打開項目準備開搞的時候發現一個問題,這個項目是提供rest服務的一個web項目,其中不少舊系統因爲還沒改爲微服務,因此只能經過HttpClient發起調用。以前的開發人員爲了監控每一個方法的執行時間,在方法開始和結束寫了不少logger.info("耗時:"+time)這種代碼。很顯然這是不規範的,當項目裏處處有這樣的代碼存在下降了代碼的可讀性,因而改造後以下:java

  

   #建立一個方法攔截器:

/**
 * 用來監控方法的執行時間-- 對應配置文件是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就是須要被打印的類。web

總結:

   經過spring 代理,不只減小了代碼的copy工做,同時又方便管理;至於後續若是有新的類須要實現打印功能,咱們只須要在spring-mvc.xml裏配置好對應的bean就能實現日誌的打印。

相關文章
相關標籤/搜索