Mybatis 플러그인 기능은 AOP와 비슷하게 동작한다. 특정 인터페이스의 메소드를 지정하면 그 인터페이스의 메소드가 실행되지 직전에 플러그인으로 등록한 클래스가 호출된다. AOP처럼 특정 메소드를 언제 어디서 어떻게 호출할지를 정할 수 있으며 수행하기 전과 후에 부가적인 기능을 넣을 수 있다.
Mybatis에서 제공해주는 Plugins 클래스는 아래와 같다.
@Bean
public SqlSessionFactoryBean sqlSessionFactory(DataSource dataSource) throws IOException {
SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();
factoryBean.setPlugins(new DynamicSQLInterceptor()); //Mybatis Plug-In 설정
factoryBean.setDataSource(dataSource);
factoryBean.setConfigLocation(applicationContext.getResource("classpath:/mybatis/mybatis-config.xml"));
factoryBean.setMapperLocations(applicationContext.getResources("classpath:/mapper/**/*Mapper.xml"));
return factoryBean;
}
ibatis에서 제공하는 @Intercepts라는 어노테이션을 지정하고, Interceptor 인터페이의 intercept(Invocation invocation) 메서드를 구현해야한다.
Property | 내용 |
type | Plugin 클래스가 들어가는 자리. Executor, ParameterHandler, ResultSetHandler, StatementHandler |
method | 각각의 type에서 제공하는 인터셉터 구간을 지정한다. StatementHandler 의 경우 (prepare, parameterize, batch, update, query) |
args | 각각의 type들은 인터페이스 형태로 되어있는데 method들에 대한 추상메서드들이 있다. 추상메서드의 파라미터값을 넣는다. |
@Intercepts({
@Signature(type= StatementHandler.class, method = "prepare", args = {Connection.class, Integer.class}),
@Signature(type= StatementHandler.class, method = "parameterize", args = {Statemennt.class})
})
인터셉터는 여러 개 지정할 수 있다. 예를 들어 StatementHandler 타입으로 prepare, parameterize 작업 중에 가로채고 싶다면 아래와 같이 설정한다.
@Intercepts
@Signature
public Object intercept(Invocation invocation) throws Throwable {
// pre processing
Object returnObject = invocation.proceed();
// post processing
return returnObject;
}
Spring AOP와 비슷할 것이다. Invocation은 Mybatis가 Interceptor 한 대상정보가 들어가 있다.
Interceptor 하여 전처리, 후처리 프로세스를 추가할 수 있다.
package org.apache.ibatis.executor.statement;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.List;
import org.apache.ibatis.cursor.Cursor;
import org.apache.ibatis.executor.parameter.ParameterHandler;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.session.ResultHandler;
/**
* @author Clinton Begin
*/
public interface StatementHandler {
Statement prepare(Connection connection, Integer transactionTimeout)
throws SQLException;
void parameterize(Statement statement)
throws SQLException;
void batch(Statement statement)
throws SQLException;
int update(Statement statement)
throws SQLException;
<E> List<E> query(Statement statement, ResultHandler resultHandler)
throws SQLException;
<E> Cursor<E> queryCursor(Statement statement)
throws SQLException;
BoundSql getBoundSql();
ParameterHandler getParameterHandler();
}
메소드 prepare, parameterize, batch, update에 대한 내용은 아래 블로그를 참조 바란다. 잘 정리되어있다.
https://aridom.tistory.com/m/71
package com.crocodile.mpm.common.interceptort;
import java.sql.Connection;
import java.util.Properties;
import org.apache.ibatis.executor.parameter.ParameterHandler;
import org.apache.ibatis.executor.statement.StatementHandler;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.plugin.Intercepts;
import org.apache.ibatis.plugin.Invocation;
import org.apache.ibatis.plugin.Plugin;
import org.apache.ibatis.plugin.Signature;
import org.apache.ibatis.reflection.MetaObject;
import org.apache.ibatis.reflection.SystemMetaObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@Intercepts(
{@Signature
(type = StatementHandler.class
, method = "prepare"
, args = {Connection.class, Integer.class})})
public class DynamicSQLInterceptor implements Interceptor{
@Override
public Object intercept(Invocation invocation) throws Throwable {
StatementHandler statementHandler = (StatementHandler) invocation.getTarget();
MetaObject metaStatementHandler = SystemMetaObject.forObject(statementHandler);
//Interceptor한 SQL
String originalSql = (String) metaStatementHandler.getValue("delegate.boundSql.sql");
//파라미터
Object paramObj = statementHandler.getParameterHandler().getParameterObject();
StringBuffer sql = new StringBuffer();
sql.append("SELECT *\n");
sql.append("FROM (\n");
sql.append(originalSql);
sql.append("\t)\n");
//변경된 SQL 설정
metaStatementHandler.setValue("delegate.boundSql.sql", sql.toString());
return invocation.proceed();
}
//파라미터로 전달받는 target객체는 실제 타겟이 되는 대상으로 현재 플러그인과 연결해 준다.
@Override
public Object plugin(Object target) {
return Plugin.wrap(target, this);
}
@Override
public void setProperties(Properties properties) {
}
}
SpringBoot logback 파일적재 (2) | 2021.10.27 |
---|---|
SpringBoot logback / log4jdbc 설정 (4) | 2021.10.19 |
Spring JPA란 (1) | 2021.10.17 |
Spring AOP Transaction설정 (0) | 2021.10.16 |
[DBCP] HikariCP (8) | 2021.10.12 |
댓글 영역