方法級別的java日志輸出控制(一)


前面學習了log4j以及log4j2 java日志控制,通過配置可以實現java日志的輸出級別,輸出位置,輸出格式等日志控制,甚至可通過配置控制不同java類的日志輸出方式。在大型web系統中,這些基本的日志控制可能還是不夠的。由於日志輸出是非常耗費資源的事情,特別在大型應用特定場景中。所以一般情況下只做warn或者只做error級別的日志輸出。然而,我們可能需要更加精細的日志控制,比如說想控制每一個方法的輸出級別,同時想在打印錯誤日志的時候把某一個方法的輸入參數也打印出來,以便更方便的查找問題的所在。本文將介紹通過配置文件和AOP技術控制方法級別的日志輸出。

先看LogActive日志類:

package com.lf.testLog4j.aop;

import com.google.gson.Gson;
import com.lf.testLog4j.Util.PropertiesUtil;
import com.lf.testLog4j.common.CommonLogUtil;
import com.lf.testLog4j.domain.ConfigLog;
import org.apache.commons.lang.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.aspectj.lang.JoinPoint;

import java.util.HashMap;
import java.util.Map;
import java.util.Properties;

/**
 * Created by lufei3 on 2015/7/14.
 */
public class LogActive {
    private static final Logger logger = LogManager.getLogger(LogActive.class);
    //前切入方法,該方法會在所有切入點之前執行。
    public void before(JoinPoint jp){
        //從配置文件讀取配置信息
        Properties prop = PropertiesUtil.getProperties("/ConfigCenter.properties");
        Map<String, String> map = new HashMap<String, String>((Map) prop);
        Gson gson = new Gson();
        ConfigLog configLog = null;
        String cName = jp.getThis().toString();
        Object[] args = jp.getArgs();  //獲得切入點參數列表
        String className = cName.substring(cName.lastIndexOf(".")+1,cName.lastIndexOf("@"));
        String methodName = jp.getSignature().getName();   //獲得方法名
        String key = className + "." + methodName;
        //獲取配置信息
        String configValue = map.get(key);
        try {
            configLog = gson.fromJson(configValue,ConfigLog.class);
        } catch (Exception e) {
            logger.error("Gson Format Exception!! logLevel:{}",configValue);
            e.printStackTrace();
            return;
        }
        if(configLog == null) {
            return;
        }
        //通過配置信息控制日志輸出
        String logLevel = configLog.getLevel();
        int offset = configLog.getOn();
        if(StringUtils.isBlank(logLevel)){
            logger.warn("method:{} log not config", key);
            return;
        }
        if(CommonLogUtil.isInfoEnable(logLevel,offset)) {
            logger.info("====Method:{};", key);
            if(args.length <=0){
                logger.info("===={}方法沒有參數", methodName);
            } else{
                for(int i=0; i<args.length; i++){
                    logger.info("====參數 {}:{} ", (i + 1), args[i]);
                }
            }
        }
    }
    public void after(){
        logger.info("調用完畢!!");
    }
}

  下面看具體配置信息ConfigCenter.properties:

TestLogAOP.test={"level":"TRACE","on":0}
TestLogAOP.test2={"level":"TRACE","on":1}

  配置說明執行test()方法的日志開關是0,即不打印日志;test2方法的日志級別是trace,開關為1,即可以打印trace級別的日志。而trace比info級別高,所以在LogActive 方法里info級別的日志是可以打印的。而如果level為warn或者error則info級別的日志就不會輸出。

CommonLogUtil類是用來確定是否可以輸出info級別的日志:

package com.lf.testLog4j.common;

/**
 * Created by lufei3 on 2015/7/20.
 */
public class CommonLogUtil {
    public static boolean isInfoEnable(String logLevel,int offset) {
        if (offset == 1&&(logLevel.equalsIgnoreCase(LogLevelEnum.INFO_LEVEL.getLogLevel())
                ||logLevel.equalsIgnoreCase(LogLevelEnum.DEBUG_LEVEL.getLogLevel())
                ||logLevel.equalsIgnoreCase(LogLevelEnum.TRACE_LEVEL.getLogLevel()))){
            return true;
        }
        return false;
    }
}

  Spring配置如下:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"
       default-autowire="byName">
    <bean id="logActive" class="com.lf.testLog4j.aop.LogActive"></bean> <!--將日志類注入到bean中。-->
    <bean id="testLogAOP" class="com.lf.testLog4j.service.TestLogAOP"></bean>

    <aop:aspectj-autoproxy proxy-target-class="true"/>
    <aop:config>
        <!--攔截service層的所有方法-->
        <aop:pointcut id="service" expression="execution(* com.lf.testLog4j.service.*.*(..))"/>
        <aop:aspect id="log" ref="logActive">
            <aop:before pointcut-ref="service" method="before"/>
            <aop:after pointcut-ref="service" method="after"/>
        </aop:aspect>
    </aop:config>
</beans>

 TestLogAOP類:

package com.lf.testLog4j.service;

import org.springframework.stereotype.Component;

/**
 * Created by lufei3 on 2015/7/14.
 */
@Component
public class TestLogAOP {
    public void test(){
        System.out.println("測試類的test方法被調用");
    }
    public void test2() {
        System.out.println("測試2的方法被調用!");
    }
}

  最后main方法:

package com.lf.testLog4j;

import com.lf.testLog4j.service.TestLogAOP;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * Created by lufei3 on 2015/7/14.
 */

public class LogAOPMain {
    @Autowired
    public static void main(String... args) {
        ApplicationContext act = new ClassPathXmlApplicationContext("spring/spring-config.xml");
        TestLogAOP testLogAOP = (TestLogAOP) act.getBean("testLogAOP");
        testLogAOP.test();
        testLogAOP.test2();
    }
}

  輸出:

測試類的test方法被調用
13:43:35.673 [main] INFO  com.lf.testLog4j.aop.LogActive - 調用完畢!!
13:43:35.713 [main] INFO  com.lf.testLog4j.aop.LogActive - ====Method:TestLogAOP.test2;
13:43:35.713 [main] INFO  com.lf.testLog4j.aop.LogActive - ====test2方法沒有參數
測試2的方法被調用!
13:43:35.714 [main] INFO  com.lf.testLog4j.aop.LogActive - 調用完畢!!

  可以看出日志根據配置文件打印了TestLogAOP.test2方法調用前后的日志輸出。

本文地址:http://www.cnblogs.com/danseqianbi/p/4685570.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM