Spring AOP를 이용한 SQL로깅(?를파라미터로 치환하여 DML로그출력),Spring JDBC로깅,Spring Framework의 JdbcOperations을 포인트컷으로 해서 모든 SQL에 대해 로깅 충고 - 스프링실무교육학원
1. 로깅을 위한 Aspcet 작성
package onj.board.aop;
import org.slf4j.Logger;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.beans.factory.annotation.Autowired;
import org.slf4j.LoggerFactory;
@Aspect
public class LoggingAspect {
private final Logger logger = LoggerFactory.getLogger(LoggingAspect.class);
// 사전충고
// Spring Framework의 JdbcOperations을 포인트컷으로 해서 모든 SQL에 대해 로깅 충고가 적용
@Before("execution(* org.springframework.jdbc.core.JdbcOperations.*(String, ..))")
public void logBefore(JoinPoint joinPoint) {
logger.info("<<<<<<<<<<<<<<<<< DAO 로깅 충고 실행");
Object[] methodArgs = joinPoint.getArgs(), sqlArgs = null;
// 실행시킨 SQL 문장
String statement = methodArgs[0].toString(); // ? 가 포함된 SQL문
// find the SQL arguments (parameters)
for (int i = 1, n = methodArgs.length; i < n; i++) {
Object arg = methodArgs[i];
if (arg instanceof Object[]) {
sqlArgs = (Object[]) arg;
break;
}
}
// '?' 대신 파라미터로 대체
String completedStatement = (sqlArgs == null ?
statement : fillParameters(statement, sqlArgs));
logger.info(completedStatement);
}
//SQL문장의 ?를 넘겨주는 파라미터로 대체해서 최종SQL문을 리턴
private String fillParameters(String statement, Object[] sqlArgs) {
// initialize a StringBuilder with a guesstimated final length
StringBuilder completedSqlBuilder = new StringBuilder(Math.round(statement.length() * 1.2f));
int index, // will hold the index of the next ?
prevIndex = 0; // will hold the index of the previous ? + 1
// loop through each SQL argument
for (Object arg : sqlArgs) {
index = statement.indexOf("?", prevIndex);
if (index == -1)
break; // bail out if there's a mismatch in # of args vs. ?'s
// append the chunk of SQL coming before this ?
completedSqlBuilder.append(statement.substring(prevIndex, index));
// append the replacement for the ?
if (arg == null)
completedSqlBuilder.append("NULL");
else
completedSqlBuilder.append(":"+arg.toString());
prevIndex = index + 1;
}
// add the rest of the SQL if any
if (prevIndex != statement.length())
completedSqlBuilder.append(statement.substring(prevIndex));
return completedSqlBuilder.toString();
}
}
2. XML 설정파일에서
<?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:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
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-4.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">
<aop:aspectj-autoproxy />
<context:component-scan base-package="onj.board.dao" />
<context:component-scan base-package="onj.board.service" />
<!-- JdbcTemplate -->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"
p:dataSource-ref="dataSource" />
<!-- wire the JdbcTemplate into your DAO (Alternatively, you could use autowiring) -->
<bean id="boardDAO" class="onj.board.dao.BoardDAOImpl"/>
<!-- AOP를 적용하여 DML처리시 로깅을 위한 것 -->
<bean id="myLogger" class="onj.board.aop.LoggingAspect" />
</beans>
3. DAO 파일에서는 jdbcTemplate을 어노테이션을 이용하여 주입받자.
@Repository("boardDAO")
public class BoardDAOImpl implements BoardDAO {
@Autowired
private JdbcOperations jdbcTemplate;
.............................
}
이제 Spring JDBC를 통하여 실행되는 모든 SQL문은 로깅이 된다.
댓글 없음:
댓글 쓰기