my batis SQL 조회 차단 수정 상세 설명 실현

머리말
차단기 의 한 역할 은 바로 우리 가 어떤 방법의 호출 을 차단 할 수 있다 는 것 이다.우 리 는 이러한 차단 되 는 방법 이 실 행 된 전후 에 어떤 논 리 를 추가 할 수도 있 고,이러한 차단 되 는 방법 을 실행 할 때 자신의 논 리 를 실행 할 수도 있 으 며,더 이상 차단 되 는 방법 을 실행 하지 않 을 수도 있다.
Mybatis 차단기 디자인 의 취 지 는 사용자 가 언젠가 자신의 논 리 를 실현 할 수 있 도록 하기 위해 Mybatis 고유의 논 리 를 건 드 리 지 않 아 도 된다 는 것 이다.예 를 들 어 저 는 모든 SQL 에 대해 고정된 작업 을 수행 하고 싶 습 니 다.SQL 조회 에 대해 안전 검 사 를 실시 하거나 관련 SQL 조회 로 그 를 기록 하고 싶 습 니 다.
Mybatis 는 사용자 정의 차단 기 를 실현 할 수 있 는 Interceptor 인 터 페 이 스 를 제공 합 니 다.

 public interface Interceptor {
 Object intercept(Invocation invocation) throws Throwable;
 Object plugin(Object target);
 void setProperties(Properties properties);
}
인터페이스 에는 세 가지 방법 정의 가 포함 되 어 있다.
intercept 방법 은 구체 적 인 차단 대상 의 처리 방법 으로 들 어 오 는 Invocation 은 목표 류 를 차단 하 는 실력,차단 하 는 방법 과 방법의 입 매개 변수 그룹 을 포함한다.Invocation 의 procced 를 사용 하여 원 함 수 를 실행 합 니 다.
plugin 에서 차단 을 할 지 여 부 를 판단 합 니 다.차단 이 필요 하지 않 으 면 target 으로 돌아 갑 니 다.차단 이 필요 하 다 면 plugin 류 의 wrap 정적 방법 을 호출 합 니 다.현재 차단기 가 임의의 인 터 페 이 스 를 실현 하면 프 록 시 대상 을 되 돌려 줍 니 다.그렇지 않 으 면 바로 돌아 갑 니 다(메모리 프 록 시 모드 의 디자인).프 록 시 대상 은 실제 Plugin 클래스 의 인 스 턴 스 입 니 다.Invocation Handler 인 터 페 이 스 를 실 현 했 습 니 다.Invocation Handler 인 터 페 이 스 는 invoke 방법 만 포함 하여 리 셋 방법 에 사 용 됩 니 다.
프 록 시 대상 의 인터페이스 방법 을 실행 할 때 Plugin 의 invoke 방법 을 호출 합 니 다.실행 할 대상,방법 과 파 라 메 터 를 Invocation 대상 으로 포장 하여 차단기 의 intercept 방법 에 전달 합 니 다.Invocation 은 차단 되 는 원래 방법 을 실행 하기 위해 procced 방법 을 정의 합 니 다.
플러그 인 클래스 정의

public class Plugin implements InvocationHandler {
 
 private Object target;
 private Interceptor interceptor;
 private Map, Set> signatureMap;
 
 private Plugin(Object target, Interceptor interceptor, Map, Set> signatureMap) {
  this.target = target;
  this.interceptor = interceptor;
  this.signatureMap = signatureMap;
 }
 
 public static Object wrap(Object target, Interceptor interceptor) {
  Map, Set> signatureMap = getSignatureMap(interceptor);
  Class type = target.getClass();
  Class[] interfaces = getAllInterfaces(type, signatureMap);
  if (interfaces.length > 0) {
   return Proxy.newProxyInstance(
     type.getClassLoader(),
     interfaces,
     new Plugin(target, interceptor, signatureMap));
  }
  return target;
 }
 
 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
  try {
   Set methods = signatureMap.get(method.getDeclaringClass());
   if (methods != null && methods.contains(method)) {
    return interceptor.intercept(new Invocation(target, method, args));
   }
   return method.invoke(target, args);
  } catch (Exception e) {
   throw ExceptionUtil.unwrapThrowable(e);
  }
 }
 
 private static Map, Set> getSignatureMap(Interceptor interceptor) {
  Intercepts interceptsAnnotation = interceptor.getClass().getAnnotation(Intercepts.class);
  if (interceptsAnnotation == null) { // issue #251
   throw new PluginException("No @Intercepts annotation was found in interceptor " + interceptor.getClass().getName());   
  }
  Signature[] sigs = interceptsAnnotation.value();
  Map, Set> signatureMap = new HashMap, Set>();
  for (Signature sig : sigs) {
   Set methods = signatureMap.get(sig.type());
   if (methods == null) {
    methods = new HashSet();
    signatureMap.put(sig.type(), methods);
   }
   try {
    Method method = sig.type().getMethod(sig.method(), sig.args());
    methods.add(method);
   } catch (NoSuchMethodException e) {
    throw new PluginException("Could not find method on " + sig.type() + " named " + sig.method() + ". Cause: " + e, e);
   }
  }
  return signatureMap;
 }
 
 private static Class[] getAllInterfaces(Class type, Map, Set> signatureMap) {
  Set> interfaces = new HashSet>();
  while (type != null) {
   for (Class c : type.getInterfaces()) {
    if (signatureMap.containsKey(c)) {
     interfaces.add(c);
    }
   }
   type = type.getSuperclass();
  }
  return interfaces.toArray(new Class[interfaces.size()]);
 }
 
}
setProperties 방법 은 말 그대로 속성 을 설정 하 는 데 사 용 됩 니 다.bean 의 속성 초기 화 방법 은 매우 많은 데,이것 은 그 중의 하나 입 니 다.
my batis 는 현재 클래스 가 차단기 임 을 설명 하 는@Intercepts 주 해 를 제공 합 니 다.그 값 은@Signature 배열 로 차단 할 인터페이스,방법 및 대응 하 는 매개 변수 유형 을 표시 합 니 다.

@Intercepts({@Signature(method = "prepare", type = StatementHandler.class, args = {Connection.class}),
    @Signature(method = "query", type = StatementHandler.class, args = {java.sql.Statement.class, ResultHandler.class})})
public class TenantInterceptor implements Interceptor {
.....
예 를 들 어 위의 클래스 성명 에서 첫 번 째 Signature 레이 블 은 StatementHandler 클래스 의 입 참 을 차단 하 는 것 은 Connection 이라는 prepare 라 는 방법 입 니 다.
두 번 째 Signature 는 StatementHandler 클래스 에 2 개의 입 참(각각 Statement 과 ResultHandler 형식)을 포함 하 는 query 라 는 방법 을 표시 합 니 다.
마지막 으로 성명 한 Interceptor 는 my batis 의 plug 에 등록 해 야 효력 이 발생 합 니 다.

  <!--   mybatis -->
  <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
    <property name="dataSource" ref="dataSource"/>
    <property name="configLocation" value="classpath:mybatis/mybatis-config.xml"/>
    <!-- mapper   -->
    <property name="mapperLocations" value="classpath:mybatis/*/*.xml"/>
    <property name="plugins">
      <array>
        <!--          -->
        <bean id="paginationInterceptor" class="xxx.xxx.TenantInterceptor">
        </bean>
      </array>
    </property>
  </bean>
이상 이 바로 본 고의 모든 내용 입 니 다.여러분 의 학습 에 도움 이 되 고 저 희 를 많이 응원 해 주 셨 으 면 좋 겠 습 니 다.

좋은 웹페이지 즐겨찾기