Spring AOP监控SQL执行

标签: spring aop 监控 | 发表时间:2014-08-27 00:20 | 作者:fangchao2061
出处:http://blog.csdn.net

         对数据库连接池Proxool比较熟悉的读者,都知道Proxool可以记录SQL执行内容和时间等信息日志。我们可以将该日志记录专门的SQL日志文件,对于查找执行特别耗时的SQL起了不小的作用。对于一些其他连接池,没有该特性时,本文介绍Spring AOP切面方法来记录SQL日志。

当然也可以通过数据库提供的特性来查询执行效率较低的SQL,本文不做探讨。

 

         本文介绍使用SpringJdbcTemplate执行SQL,使用其他方法或者ORM思路类似(Hibernate提供了日志记录功能)。

 

         使用AOP,可以使用Around通知,在JdbcTemplate执行方法前,记录当前时间,在方法执行完后,计算SQL耗时,并记录日志。思路很简单,不过多介绍,代码如下。


package org.enyes.sql.util;
import org.apache.log4j.Logger;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;

/**
 * 对Spring JdbcTemplate进行切面,记录每个sql执行时间。
 */
@Aspect
public class SqlExecutionTimeAspect {
	/**
	 * logger
	 */
	private static final Logger LOG = Logger
			.getLogger(SqlExecutionTimeAspect.class);

	/**
	 * 当Sql执行时间超过该值时,则进行log warn级别题型,否则记录INFO日志。
	 */
	private long warnWhenOverTime = 2 * 60 * 1000L;

	@Around("execution(* org.springframework.jdbc.core.JdbcTemplate.*(..))")
	public Object logSqlExecutionTime(ProceedingJoinPoint joinPoint)
			throws Throwable {
		long startTime = System.currentTimeMillis();
		Object result = joinPoint.proceed();
		long costTime = System.currentTimeMillis() - startTime;
		if (costTime > warnWhenOverTime) {
			StringBuilder sb = new StringBuilder();
			sb.append("execute method :").append(joinPoint.getSignature());
			sb.append("args: ").append(arrayToString(joinPoint.getArgs()));
			sb.append(" cost time[").append(costTime).append("]ms");
			LOG.warn(sb);
		} else if (LOG.isInfoEnabled()) {
			StringBuilder sb = new StringBuilder();
			sb.append("execute method :").append(joinPoint.getSignature());
			sb.append("args: ").append(arrayToString(joinPoint.getArgs()));
			sb.append(" cost time[").append(costTime).append("]ms");
			LOG.info(sb);
		}
		return result;
	}

	private static String arrayToString(Object[] a) {
		if (a == null)
			return "null";

		int iMax = a.length - 1;
		if (iMax == -1)
			return "[]";

		StringBuilder b = new StringBuilder();
		b.append('[');
		for (int i = 0;; i++) {
			if (a[i] instanceof Object[]) {
				b.append(arrayToString((Object[]) a[i]));
			} else {
				b.append(String.valueOf(a[i]));
			}
			if (i == iMax)
				return b.append(']').toString();
			b.append(", ");
		}
	}
}

Springxml配置如下:

<?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:p="http://www.springframework.org/schema/p"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:tx="http://www.springframework.org/schema/tx"
	xmlns:aop="http://www.springframework.org/schema/aop"
	xmlns:task="http://www.springframework.org/schema/task" 
	xsi:schemaLocation="  
    http://www.springframework.org/schema/beans   
    http://www.springframework.org/schema/beans/spring-beans-3.1.xsd  
    http://www.springframework.org/schema/context  
    http://www.springframework.org/schema/context/spring-context-3.1.xsd  
    http://www.springframework.org/schema/mvc  
    http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd 
     http://www.springframework.org/schema/tx 
    http://www.springframework.org/schema/tx/spring-tx-3.1.xsd 
     http://www.springframework.org/schema/aop
    http://www.springframework.org/schema/aop/spring-aop-3.1.xsd  
    http://www.springframework.org/schema/task 
    http://www.springframework.org/schema/task/spring-task-3.1.xsd 
">
<beans>
<aop:aspectj-autoproxy proxy-target-class="true"/>
<bean class="org.enyes.sql.util.SqlExecutionTimeAspect"/>
</beans>

可以使用Log4J将SqlExecutionTimeAspect类的日志打印到专门的日志中,并且warnWhenOverTime提供setter方法,可以通过Spring xml来具体配置。

完毕。






作者:fangchao2061 发表于2014-8-26 16:20:46 原文链接
阅读:65 评论:1 查看评论

相关 [spring aop 监控] 推荐:

Spring AOP监控SQL执行

- - CSDN博客架构设计推荐文章
         对数据库连接池Proxool比较熟悉的读者,都知道Proxool可以记录SQL执行内容和时间等信息日志. 我们可以将该日志记录专门的SQL日志文件,对于查找执行特别耗时的SQL起了不小的作用. 对于一些其他连接池,没有该特性时,本文介绍Spring AOP切面方法来记录SQL日志.

Spring AOP详解

- - Java - 编程语言 - ITeye博客
        最近项目中遇到了以下几点需求,仔细思考之后,觉得采用AOP来解决. 一方面是为了以更加灵活的方式来解决问题,另一方面是借此机会深入学习Spring AOP相关的内容. 例如,以下需求不用AOP肯定也能解决,至于是否牵强附会,仁者见仁智者见智. 1.对部分函数的调用进行日志记录,用于观察特定问题在运行过程中的函数调用情况.

Java Spring注解任务调度并实现AOP监控任务执行情况

- - 极客521 | 极客521
本文讲的是通过Spring注解的方式实现任务调度. 只要引入了spring-context包就能够在项目中使用注解方式的任务调度. 需要在Spring配置文件中加入task的schema. 然后在代码中就可以直接用了,要定时执行的方法必须是void的,并且没有任何参数的. cron表达式请自行问百度,下面只列出几个从网上找的例子.

Spring AOP 实现原理与 CGLIB 应用

- - 博客 - 伯乐在线
来源: IBM Developerworks. 简介: AOP(Aspect Orient Programming),也就是面向方面编程,作为面向对象编程的一种补充,专门用于处理系统中分布于各个模块(不同方法)中的交叉关注点的问题,在 Java EE 应用中,常常通过 AOP 来处理一些具有横切性质的系统级服务,如事务管理、安全检查、缓存、对象池管理等.

Spring AOP 代理机制 JDK&CGLIB

- - 开源软件 - ITeye博客
Spring AOP使用JDK动态代理或者CGLIB来为目标对象创建代理. (建议优先使用JDK的动态代理). 如果被代理的目标对象实现了至少一个接口,则会使用JDK动态代理. 所有该目标类型实现的接口都将被代理. 若该目标对象没有实现任何接口,则创建一个CGLIB代理. 如果你希望强制使用CGLIB代理,(例如:希望代理目标对象的所有方法,而不只是实现自接口的方法) 那也可以.

使用spring AOP获得session的思路

- - RSS - IT博客云
由于Spring 的AOP面向切面编程,与Servlet容器没有任何关联,所以想要获得Session会话比较麻烦. 当然Struts2同样不依赖Servlet容器,可以在Spring AOP中可以使用 com.opensymphony.xwork2.ActionContext,就可以获得 Session.

Spring AOP + Redis缓存数据库查询

- - 编程语言 - ITeye博客
我们希望能够将数据库查询结果缓存到Redis中,这样在第二次做同样的查询时便可以直接从redis取结果,从而减少数据库读写次数. 必须要做到与业务逻辑代码完全分离. 从缓存中读出的数据必须与数据库中的数据一致. 如何为一个数据库查询结果生成一个唯一的标识. Key),能唯一确定一个查询结果,同一个查询结果,一定能映射到同一个.

Spring AOP动态代理原理与实现方式 (转)

- - 开源软件 - ITeye博客
AOP:面向切面、面向方面、面向接口是一种横切技术. 1.事务管理: (1)数据库事务:(2)编程事务(3)声明事物:Spring AOP-->声明事物   . 3.安全验证: Spring AOP---OOP升级  . 静态代理原理:目标对象:调用业务逻辑    代理对象:日志管理. 表示层调用--->代理对象(日志管理)-->调用目标对象.

基于 Annotation 拦截的 Spring AOP 权限验证方法

- - 企业架构 - ITeye博客
转自: http://www.ibm.com/developerworks/cn/java/j-lo-springaopfilter/index.html. 使用 Annotation 可以非常方便的根据用户的不同角色,分配访问 Java 方法的权限. 在 Java Web 开发中,使用这种方法,可以提高系统的松耦合度,方便维护.

Spring aop 原理及各种应用场景

- - 开源软件 - ITeye博客
AOP是Aspect Oriented Programing的简称,面向切面编程. AOP适合于那些具有横切逻辑的应用:如性能监测,访问控制,事务管理、缓存、对象池管理以及日志记录. AOP将这些分散在各个业务逻辑中的代码通过横向切割的方式抽取到一个独立的模块中. AOP 实现的关键就在于 AOP 框架自动创建的 AOP 代理,AOP 代理则可分为静态代理和动态代理两大类,其中静态代理是指使用 AOP 框架提供的命令进行编译,从而在编译阶段就可生成 AOP 代理类,因此也称为编译时增强;而动态代理则在运行时借助于 JDK 动态代理、CGLIB 等在内存中“临时”生成 AOP 动态代理类,因此也被称为运行时增强.