Эта статья является кратким изложением книги «MyBatis простыми словами: технические принципы и практика».
Последняя статья представилаАнализ и принцип работы MyBatis, включая построение SqlSessionFactory и процесс выполнения SqlSession. Среди них SqlSession содержит четыре основных объекта. Вы можете вставить пользовательский код, когда четыре основных объекта запланированы для удовлетворения особых потребностей. Это технология подключаемых модулей, предоставляемая MyBatis.
Индекс серии:
- Введение в JDBC и MyBatis
- Все конфигурации MyBatis
- "Маппер" все понимают
- Основы отражения и динамических прокси
- Анализ и принцип работы MyBatis
В некоторых особых сценариях необходимо использовать подключаемые модули для унифицированной обработки. Например, когда выполняется многопользовательская разработка, данные должны быть изолированы арендатором. Вы можете единообразно добавить условия фильтрации идентификатора арендатора после оператора SQL.
В этой статье мы познакомим вас с плагином. Благодаря знакомству с этой статьей вы узнаете:
- Интерфейс плагина и инициализация
- Прокси и дизайн отражения для плагинов
- Введение в класс инструментов MetaObject
- Процесс разработки плагина
Интерфейс плагина и анализ инициализации
Интерфейс плагина
MyBatis в плагине, необходимо реализовать Interceptor определяется следующим образом:
public interface Interceptor {
Object intercept(Invocation invocation) throws Throwable;
Object plugin(Object target);
void setProperties(Properties properties);
}
Расскажите подробнее об этих трех методах:
- перехват: Он будет напрямую перезаписывать объект, который вы перехватили.Существует параметр Invocation object, через который может быть отражен метод планирования исходного объекта;
- плагин: цель — перехватываемый объект, его функция — генерировать прокси-объект для перехваченного объекта;
- setProperties: позволяет настроить необходимые параметры в элементе плагина, этот метод будет вызываться один раз при инициализации плагина;
инициализация плагина
Инициализация плагина завершается при инициализации MyBatis, считываются узел плагина и параметры конфигурации, генерируется экземпляр плагина с использованием технологии рефлексии, после чего вызывается метод setProperties в методе плагина для установки параметров, а экземпляр плагина сохраняется в объекте конфигурации. См. код ниже для процесса.
Пример конфигурации плагина выглядит следующим образом:
<plugins>
<plugin interceptor="com.qqdong.study.mybatis.TenantPlugin">
<property name="dbType" value="mysql"/>
</plugin>
<plugins>
Процесс инициализации плагина:
public class XMLConfigBuilder extends BaseBuilder {
......
private void pluginElement(XNode parent) throws Exception {
if (parent != null) {
for (XNode child : parent.getChildren()) {
String interceptor = child.getStringAttribute("interceptor");
Properties properties = child.getChildrenAsProperties();
Interceptor interceptorInstance = (Interceptor) resolveClass(interceptor).newInstance();
interceptorInstance.setProperties(properties);
configuration.addInterceptor(interceptorInstance);
}
}
}
......
}
Добавить метод плагина объекта конфигурации Конфигурация:
public class Configuration {
protected final InterceptorChain interceptorChain = new InterceptorChain();
public void addInterceptor(Interceptor interceptor) {
interceptorChain.addInterceptor(interceptor);
}
}
InterceptorChain — это класс, который в основном содержит свойство List, сохраняющее объекты Interceptor:
public class InterceptorChain {
private final List<Interceptor> interceptors = new ArrayList<Interceptor>();
public Object pluginAll(Object target) {
for (Interceptor interceptor : interceptors) {
target = interceptor.plugin(target);
}
return target;
}
public void addInterceptor(Interceptor interceptor) {
interceptors.add(interceptor);
}
public List<Interceptor> getInterceptors() {
return Collections.unmodifiableList(interceptors);
}
}
Принципы дизайна прокси и отражения для плагинов
Модель цепочки ответственности
Плагин использует цепь образец ответственности, которая является структурой поведения объекта. В цепочке модели ответственности многие объекты подключаются к ссылке каждого объекта на его подчиненное образование цепочки, и запрос передается на эту цепочку до тех пор, пока объект на цепочке не решит обрабатывать запрос.
планировать детали
Упомянутый ранее класс InterceptorChain имеет метод pluginAll, в котором определяется цепочка ответственности.
public Object pluginAll(Object target) {
for (Interceptor interceptor : interceptors) {
target = interceptor.plugin(target);
}
return target;
}
Метод плагина был представлен выше, это метод генерации прокси-объекта, начиная с первого объекта (одного из четырех основных объектов), объект передается в метод плагина и возвращается прокси, если есть второй plugin, take Первый прокси-объект, переданный методу плагина, возвращает прокси первого прокси-объекта...
Метод плагина должен быть реализован нами. Как сгенерировать класс прокси? MyBatis предоставляет класс инструмента Plugin, который реализует интерфейс InvocationHandler (интерфейс динамического прокси JDK). Давайте посмотрим на его два метода:
public class Plugin implements InvocationHandler {
public static Object wrap(Object target, Interceptor interceptor) {
Map<Class<?>, Set<Method>> 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;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
try {
Set<Method> 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);
}
}
}
Анализируя этот код, подключаемый модуль предоставляет метод переноса статического метода, который генерирует прокси-класс в соответствии с конфигурацией подписи подключаемого модуля, используя динамический прокси-метод JDK, когда четыре основных объекта выполняют метод, метод вызова подключаемого модуля будет Если метод включен в объявленную сигнатуру, будет вызван метод перехвата пользовательского плагина с передачей объекта Invocation.
Кроме того, объект Invocation содержит метод continue, который является реальным методом вызова прокси-объекта.Если плагинов n, то первым переданным параметром являются сами четыре объекта, а затем один раз вызывается метод wrap для генерации первый прокси-объект. Отражение здесь — это реальный метод четырех основных объектов. Если есть второй подключаемый модуль, отражение здесь — это метод вызова первого прокси-объекта.
Таким образом, в случае нескольких плагинов планируйте метод Proceed, Mybatis всегда запускается от последнего прокси-объекта к первому прокси-объекту, и, наконец, выполняется метод реального заблокированного объекта.
Введение в класс инструментов MetaObject
MetaObject — это класс инструментов, предоставленный MyBatis, который может эффективно получать или изменять свойства некоторых важных объектов.
Например, мы перехватываем объект StatementHandler.Во-первых, нам нужно получить SQL для выполнения и добавить ограничение на количество возвращаемых строк.
Напишите собственный плагин и реализуйте метод перехвата.Метод реализован следующим образом
StatementHandler statementHandler=(StatementHandler)invocation.getTarget();
MetaObject metaObj=SystemMetaObject.forObject(statementHandler);
//获取sql
String sql=(String)metaStatementHandler.getValue("delegate.bound.sql");
//添加limit条件
sql="select * from (" + sql + ") limit 1000";
//重新设置sql
metaStatementHandler.setValue("delegate.bound.sql",sql);
Процесс разработки плагина
Наконец, суммируйте этапы разработки плагина.
Уверен, что вы хотите перехватить подписи
- Определить объект для перехвата, один из четырех основных объектов;
- Определить методы и параметры перехвата;
Например, если вы хотите перехватить метод prepare объекта StatementHandler, этот метод имеет параметр объекта Connection, который можно объявить следующим образом:
@Intercepts({
@Signature(type =StatementHandler.class,
method="prepare" ,
args={Connection.class})})
public class MyPlugin implements Interceptor{
......
}
Определите класс подключаемого модуля и реализуйте метод перехвата
Принцип был проанализирован выше, и достаточно метода реализации интерфейса Interceptor.Инструментальный класс Plugin используется для простого создания прокси-класса, а инструментальный класс MetaObject используется для простого манипулирования свойствами четырех основных объектов и модификации соответствующие значения.
настроить
Наконец, настройте пользовательский плагин:
<plugins>
<plugin interceptor="com.qqdong.study.mybatis.TenantPlugin">
<property name="dbType" value="mysql"/>
</plugin>
<plugins>
Пользовательские плагины по-прежнему относительно сложны. Если вы не понимаете принцип, это легко сделать ошибки. Постарайтесь не использовать плагины, потому что это модифицировать базовый дизайн MyBatis. Плагин генерирует цепочку от ответственности модели слой слой прокси-объектов. Он проходит через метод отражения, и производительность не высока. Он должен быть всесторонне рассмотрена, особенно логикой прокси-слоя. множества плагинов.
Добро пожаловать, чтобы отсканировать QR-код ниже и подписаться на мою личную общедоступную учетную запись WeChat~