Как получить запрос в MyBatis Interceptor

В приведенном ниже примере из Telerik используется элемент управления ShapedForm, но измените его на обычную форму Windows. Это самый легкий и лучший способ, который я видел.

http://www.telerik.com/support/kb/winforms/forms-and-dialogs/details/add-splashscreen-to-your-application

0
задан milosdju 13 July 2018 в 07:14
поделиться

1 ответ

Одно важное замечание перед тем, как я отвечу на ваш вопрос: плохой практикой является доступ к слою пользовательского интерфейса на уровне DAO. Это создает зависимость в неправильном направлении. Внешние слои вашего приложения могут обращаться к внутренним слоям, но в этом случае это наоборот. Вместо этого вам нужно создать класс, который не принадлежит ни одному слою и будет (или, по крайней мере, может) использоваться всеми слоями приложения. Его можно называть как MetricsHolder. Перехватчик может хранить в нем значения, а в другом месте, где вы планируете получать показатели, которые вы можете прочитать из него (и использовать их напрямую или хранить в запросе, если он находится в слое пользовательского интерфейса, и там доступен запрос).

Но теперь возвращаюсь к вам вопрос. Даже если вы создадите что-то вроде MetricsHolder, вы все равно столкнетесь с проблемой, которую вы не можете ввести в перехватчик mybatis.

Вы не можете просто добавить поле с аннотацией Autowired к перехватчику и ожидать он должен быть установлен. Причиной этого является то, что перехватчик создается экземпляром mybatis, а не весной. Таким образом, у весны нет возможности вводить зависимости в перехватчик.

Один из способов справиться с этим - делегировать обработку перехвата весеннему компоненту, который будет частью весеннего контекста и может получить доступ к другим компонентам. Проблема заключается в том, как сделать этот компонент доступным для перехватчика.

Это можно сделать, сохранив ссылку на такой компонент в локальной переменной потока. Вот пример, как это сделать. Сначала создайте реестр, который будет хранить весенний боб.

public class QueryInterceptorRegistry {

    private static ThreadLocal<QueryInterceptor> queryInterceptor = new ThreadLocal<>();

    public static QueryInterceptor getQueryInterceptor() {
        return queryInterceptor.get();
    }

    public static void setQueryInterceptor(QueryInterceptor queryInterceptor) {
        QueryInterceptorRegistry.queryInterceptor.set(queryInterceptor);
    }

    public static void clear() {
        queryInterceptor.remove();
    }

}

. Перехватчик запросов здесь выглядит примерно так:

public interface QueryInterceptor {
    Object interceptQuery(Invocation invocation) throws InvocationTargetException, IllegalAccessException;
}

Затем вы можете создать перехватчик, который будет делегировать обработку весной bean:

@Intercepts({
        @Signature(type = Executor.class, method = "query", args = { MappedStatement.class, Object.class,
                RowBounds.class, ResultHandler.class }),
        @Signature(type = Executor.class, method = "query", args = { MappedStatement.class, Object.class,
                RowBounds.class, ResultHandler.class, CacheKey.class, BoundSql.class}) })
public class QueryInterceptorPlugin implements Interceptor {

    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        QueryInterceptor interceptor = QueryInterceptorRegistry.getQueryInterceptor();
        if (interceptor == null) {
            return invocation.proceed();
        } else {
            return interceptor.interceptQuery(invocation);
        }
    }

    @Override
    public Object plugin(Object target) {
        return Plugin.wrap(target, this);
    }

    @Override
    public void setProperties(Properties properties) {
    }

}

Вам необходимо создать реализацию QueryInterceptor, которая делает то, что вам нужно, и сделать ее весенним бобом (здесь вы можете получить доступ к другому весеннему бобу, включая запрос, нет, как я писал выше):

@Component
public class MyInterceptorDelegate implements QueryInterceptor {

    @Autowired
    private SomeSpringManagedBean someBean;

    @Override
    public Object interceptQuery(Invocation invocation) throws InvocationTargetException, IllegalAccessException {
      // do whatever you did in the mybatis interceptor here
      // but with access to spring beans
   }
}

Теперь единственная проблема заключается в установке и очистке делегата в реестре.

Я сделал это с помощью аспекта, который был применен к моей службе (но вы можете сделать это вручную или весной mvc-перехватчик). Мой аспект выглядит так:

@Aspect
public class SqlSessionCacheCleanerAspect {

    @Autowired MyInterceptorDelegate myInterceptorDelegate;

    @Around("some pointcut that describes service methods")
    public Object applyInterceptorDelegate(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        QueryInterceptorRegistry.setQueryInterceptor(myInterceptorDelegate);
        try {
            return proceedingJoinPoint.proceed();
        } finally {
            QueryInterceptorRegistry.clear();
        }
    }

}
0
ответ дан Roman Konoval 17 August 2018 в 13:29
поделиться
Другие вопросы по тегам:

Похожие вопросы: