プラグイン・リフレクション・例外

動的プロキシによるインターセプト (org.apache.ibatis.plugin)、キャッシュ付き JavaBean / Record リフレクション (org.apache.ibatis.reflection)、およびランタイム例外階層 (org.apache.ibatis.exceptions) の API リファレンスです。

05_plugin_reflection_exceptions_1
MyBatis 3 v3.6.0 — プラグインインターセプト・MetaObject リフレクション・例外階層
Source Code
from drawlib.canvas import save, setup
from drawlib.diagrams.architecture import ArchitectureDiagram, Node, NodeGroup, PhosphorIcon
from drawlib.styles import Colors, Styles

setup(width=140, height=48, dpi=150)

d = ArchitectureDiagram(
    node_style=Styles.Dark,
    node_text_style=Styles.DarkBold.patch(text_size=9.5),
    edge_style=Styles.Dark.patch(line_width=1.5),
    edge_text_style=Styles.DarkBold.patch(text_size=9.0),
    node_card_style=Styles.Neutral.patch(shape_fill_color=Colors.White),
)

grp = d.add(
    NodeGroup(
        "横断的ランタイムサブシステム",
        width=132,
        height=22,
        style=Styles.SecondaryNeutral,
        text_style=Styles.DarkBold.patch(text_size=10.2, halign="left", valign="top"),
    ),
    xy=(4, 22),
)
n_plg = grp.add(Node("プラグインインターセプト\nInterceptor / @Intercepts / Plugin", icon=PhosphorIcon.PUZZLE_PIECE, width=38, height=13), xy=(23, 9))
n_ref = grp.add(Node("リフレクションエンジン\nMetaObject / Reflector / ObjectFactory", icon=PhosphorIcon.MAGNIFYING_GLASS, width=40, height=13), xy=(66, 9))
n_exc = grp.add(Node("例外階層\nPersistenceException と派生例外", icon=PhosphorIcon.WARNING_OCTAGON, width=38, height=13), xy=(109, 9))

n_core = d.add(
    Node("インターセプト可能なコア実行ターゲット (Executor / StatementHandler / ParameterHandler / ResultSetHandler)", icon=PhosphorIcon.CPU, width=116, height=12),
    xy=(70, 9),
)

n_plg.connect(n_core)
n_ref.connect(n_core)
n_exc.connect(n_core)

d.draw(xy=(0, 0))
save()

interfaceInterceptor#

パッケージ: org.apache.ibatis.plugin

MyBatis の 4 つのコア実行ターゲット (Executor、StatementHandler、ParameterHandler、ResultSetHandler) のメソッドをラップして処理を差し込むための拡張 SPI です。

シグネチャ#

public interface Interceptor {
  Object intercept(Invocation invocation) throws Throwable;

  default Object plugin(Object target) {
    return Plugin.wrap(target, this);
  }

  default void setProperties(Properties properties) {
    // NOP
  }
}

使用例#

@Intercepts({
  @Signature(
      type = StatementHandler.class,
      method = "prepare",
      args = {Connection.class, Integer.class})
})
public class SlowQueryCommentPlugin implements Interceptor {
  @Override
  public Object intercept(Invocation invocation) throws Throwable {
    StatementHandler handler = (StatementHandler) invocation.getTarget();
    BoundSql boundSql = handler.getBoundSql();
    // JDBC Statement 準備前に boundSql.getSql() を検査
    return invocation.proceed();
  }
}

annotation @Intercepts#

パッケージ: org.apache.ibatis.plugin

インターセプト対象とする 1 つ以上の @Signature メソッドターゲットを宣言するために Interceptor クラスに付与するコンテナアノテーションです。

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Intercepts {
  Signature[] value();
}

annotation @Signature#

パッケージ: org.apache.ibatis.plugin

インターセプト可能な 4 つのインターフェース (Executor.class、StatementHandler.class、ParameterHandler.class、ResultSetHandler.class) のいずれかにおける正確なメソッドシグネチャを指定します。

属性 型 説明
type Class<?> ターゲットインターフェース (Executor、StatementHandler、ParameterHandler、ResultSetHandler)
method String type 上のメソッド名 ("query"、"update"、"prepare" など)
args Class<?>[] type.getMethod(method, args) でオーバーロードメソッドを特定するための引数型配列

classInvocation#

パッケージ: org.apache.ibatis.plugin

Interceptor.intercept(Invocation) に渡される、インターセプトされた 1 回のメソッド呼び出しをカプセル化します。

主要メソッド#

メソッド シグネチャ 説明
getTarget Object getTarget() 基底のターゲット (または内側のプロキシ) インスタンスを返します
getMethod Method getMethod() インターセプトされた java.lang.reflect.Method を返します
getArgs Object[] getArgs() メソッド引数の変更可能な配列を返します
proceed Object proceed() throws InvocationTargetException, IllegalAccessException method.invoke(target, args) を呼び出してチェーンを続行します

classPlugin#

パッケージ: org.apache.ibatis.plugin

Interceptor 上の @Intercepts / @Signature メタデータを解析し、一致するインターフェースを java.lang.reflect.Proxy でラップする InvocationHandler 実装です。

主要メソッド#

public static Object wrap(Object target, Interceptor interceptor)

classMetaObject#

パッケージ: org.apache.ibatis.reflection

JavaBean、Java record、Map、および List / 配列コレクションを横断して、ネストされたパス式 ("author.address.city"、"orders[0].items['sku'].price") を透過的に評価できる統一プロパティナビゲーションファサードです。

主要メソッド#

メソッド シグネチャ 説明
forObject static MetaObject forObject(Object object, ObjectFactory objectFactory, ObjectWrapperFactory wrapperFactory, ReflectorFactory reflectorFactory) ファクトリメソッド (Configuration.newMetaObject(obj) または SystemMetaObject.forObject(obj) の利用を推奨)
getValue Object getValue(String name) ネストされたプロパティ式を評価して値を取得します
setValue void setValue(String name, Object value) 必要に応じて中間オブジェクトを自動生成しながら、ネストされたプロパティパスに値を書き込みます
hasGetter / hasSetter boolean hasGetter(String name) / boolean hasSetter(String name) プロパティパスが読み取り可能または書き込み可能かを判定します
findProperty String findProperty(String propName, boolean useCamelCaseMapping) カラム名をプロパティ名に照合します (オプションでアンダースコアを除去)

classSystemMetaObject#

パッケージ: org.apache.ibatis.reflection

DefaultObjectFactory、DefaultObjectWrapperFactory、DefaultReflectorFactory を用いた静的ファクトリ SystemMetaObject.forObject(Object) を提供するユーティリティクラスです。プラグイン内部で StatementHandler や RoutingStatementHandler の非公開フィールドを検査する際に便利です。


classReflector#

パッケージ: org.apache.ibatis.reflection

DefaultReflectorFactory (ConcurrentHashMap<Class<?>, Reflector>) によって管理されるクラス単位のキャッシュ済みイントロスペクションメタデータです。コンストラクタ、getter/setter の Invoker (MethodInvoker、GetFieldInvoker、SetFieldInvoker)、および TypeParameterResolver によるジェネリック戻り値・パラメータ型を事前計算します。


interfaceObjectFactory#

パッケージ: org.apache.ibatis.reflection.factory

DefaultResultSetHandler や MetaObject がデフォルトコンストラクタまたは引数付きコンストラクタ経由で結果オブジェクトをインスタンス化するために使用する SPI です (標準実装は DefaultObjectFactory)。

シグネチャ#

public interface ObjectFactory {
  default void setProperties(Properties properties) {}
  <T> T create(Class<T> type);
  <T> T create(Class<T> type, List<Class<?>> constructorArgTypes, List<Object> constructorArgs);
  <T> boolean isCollection(Class<T> type);
}

classPersistenceException#

パッケージ: org.apache.ibatis.exceptions

すべての MyBatis 例外の基底となる非チェック例外 (RuntimeException) クラスです (非推奨となった IbatisException の後継)。すべてのドメイン固有例外 (BindingException、BuilderException、CacheException、DataSourceException、ExecutorException、LogException、PluginException、ReflectionException、ScriptingException、TransactionException、TypeException) は PersistenceException を継承しています。


classTooManyResultsException#

パッケージ: org.apache.ibatis.exceptions

クエリが 0 件または 1 件ではなく 2 件以上の行を返した際に、DefaultSqlSession.selectOne(...) (および単一オブジェクトを返す Mapper インターフェースメソッド) からスローされます。