最近需要开始剥离日志逻辑,故想到了aop方式插入日志。
配置文件:
<?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-2.5.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd"> <aop:config> <aop:advisor id="serviceLog" advice-ref="methodTimeAdvice" pointcut="execution(* *..service..*(..))" /> <aop:advisor id="daoLog" advice-ref="methodTimeAdvice" pointcut="execution(* *..dao..*(..))" /> </aop:config> <bean id="methodTimeAdvice" class="com.cms5.cmservice.jms.monitor.log.MethodTimeAdvice" /> </beans>
补充一点:如果在pointcut中存在多个表达式,可以用"||"来进行分隔,如:
<aop:config> <aop:advisor id="jmsLog" advice-ref="methodTimeAdvice" pointcut="execution(* *..dao.impl..*(..))||execution(* *..service.impl..*(..))||execution(* *..front.impl..*(..))" /> </aop:config>
实际执行日志插入的类代码:
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.time.StopWatch;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
public class MethodTimeAdvice implements MethodInterceptor {
protected final Log log = LogFactory.getLog(MethodTimeAdvice.class);
/**
* 拦截要执行的目标方法
*/
@SuppressWarnings("unchecked")
public Object invoke(MethodInvocation invocation) throws Throwable {
StopWatch clock = new StopWatch();
clock.start(); // 计时开始
Object result = invocation.proceed();
clock.stop(); // 计时结束
Class[] paramsType = invocation.getMethod().getParameterTypes();
Object[] params = invocation.getArguments();
String[] simpleParams = new String[paramsType.length];
String[] paramsStr = new String[params.length];
for (int i = 0; i < paramsType.length; i++) {
simpleParams[i] = paramsType[i].getSimpleName();
}
for (int i = 0; i < params.length; i++) {
paramsStr[i] = params[i].toString();
}
log.info("METHOD:["
+ invocation.getThis().getClass().getName() + "."
+ invocation.getMethod().getName() + "("
+ StringUtils.join(simpleParams, ",") + ")]<|>" + "PARAMS: "
+ StringUtils.join(paramsStr, ",") + "<|>" + "TAKES: "
+ clock.getTime() + " ms");
return result;
}
}
主要将service层和dao层的方法信息和参数情况还有方法执行时间打印出来。下面还要进一步在logback中配置用jms来将打出的日志已消息的形式发出,供消费者接受并集中计算,这个下次再发~
开发过程中遇到一个问题,就是项目中的dao层都采用了继承带泛型类的方式,在用cglib做动态代理的时候总是报错,所以在<aop:config>中将原来的 proxy-target-class="true"的配置去掉了(当然也要满足dao层的实现类实现了一个dao接口才行,开始的代码也是上网找的,后来查了下,才将这个配置去掉了,留在这里,作为备忘)
运行测试结果:
METHOD:[com.cms5.cmsservice.jms.monitor.dao.impl.JmsMonitorDaoImpl.countByCondition(JmsMonitorPo)]<|>PARAMS: JmsMonitorPo [biz_type=null, error_message_cms_end=null, error_message_product_end=null, error_message_rate_end=null, error_message_receive_end=null, error_time_cms_end=null, error_time_product_end=null, error_time_rate_end=null, error_time_receive_end=null, id=null, is_again=null, mdmc_id=null, mdmc_music_id=null, operate_type=null, state=null, state_cms_begin=null, state_cms_end=null, state_product_begin=null, state_product_end=null, state_rate_begin=null, state_rate_end=null, state_receive_begin=null, state_receive_end=null, success_time_cms_end=null, success_time_product_end=null, success_time_rate_end=null, success_time_receive_end=null, time_cms_begin=null, time_product_begin=null, time_rate_begin=null, time_receive_begin=null, version=null]<|>TAKES: 3609 ms
METHOD:[com.cms5.cmsservice.jms.monitor.dao.impl.JmsMonitorDaoImpl.queryByCondition(int,int,JmsMonitorPo)]<|>PARAMS: 0,20,JmsMonitorPo [biz_type=null, error_message_cms_end=null, error_message_product_end=null, error_message_rate_end=null, error_message_receive_end=null, error_time_cms_end=null, error_time_product_end=null, error_time_rate_end=null, error_time_receive_end=null, id=null, is_again=null, mdmc_id=null, mdmc_music_id=null, operate_type=null, state=null, state_cms_begin=null, state_cms_end=null, state_product_begin=null, state_product_end=null, state_rate_begin=null, state_rate_end=null, state_receive_begin=null, state_receive_end=null, success_time_cms_end=null, success_time_product_end=null, success_time_rate_end=null, success_time_receive_end=null, time_cms_begin=null, time_product_begin=null, time_rate_begin=null, time_receive_begin=null, version=null]<|>TAKES: 625 ms
METHOD:[com.cms5.cmsservice.jms.monitor.service.impl.JmsMonitorServiceImpl.getPageDatas(int,int,JmsMonitorPo)]<|>PARAMS: 1,20,JmsMonitorPo [biz_type=null, error_message_cms_end=null, error_message_product_end=null, error_message_rate_end=null, error_message_receive_end=null, error_time_cms_end=null, error_time_product_end=null, error_time_rate_end=null, error_time_receive_end=null, id=null, is_again=null, mdmc_id=null, mdmc_music_id=null, operate_type=null, state=null, state_cms_begin=null, state_cms_end=null, state_product_begin=null, state_product_end=null, state_rate_begin=null, state_rate_end=null, state_receive_begin=null, state_receive_end=null, success_time_cms_end=null, success_time_product_end=null, success_time_rate_end=null, success_time_receive_end=null, time_cms_begin=null, time_product_begin=null, time_rate_begin=null, time_receive_begin=null, version=null]<|>TAKES: 4250 ms