Spring + mybatisなコンポーネントライブラリを作成する方法

Spring + mybatisを使った開発用に、DBの自動テスト用ユーティリティを作成しました
DbTestUtil https://github.com/naosim/DbTestUtil
SQL文をサクッと実行したりできます

このユーティリティでは
Spring(DI)とmybatisを使ったコンポーネントをライブラリ化してますが、設定周りが結構大変だったのでメモ

DI対象

今回作ったライブラリのDI対象は以下の2つ

DbTestComponent

https://github.com/naosim/DbTestUtil/blob/master/src/main/java/com/naosim/dbtestutil/DbTestComponent.java
内部でDbTestQueryMapperをDIしてます

DbTestQueryMapper

https://github.com/naosim/DbTestUtil/blob/master/src/main/java/com/naosim/dbtestutil/db/DbTestQueryMapper.java
mybatisのマッパー。DDLxmlではなくアノテーションで書いてます

ComponentとMapperをDIする

DbTestScanConfiguration

DbTestComponentと同列にDbTestScanConfigurationというクラスを作り、DbTestComponentとDbTestQueryMapperがDIできるようにします

package com.naosim.dbtestutil;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

@Configuration
@ComponentScan("com.naosim.dbtestutil")
@MapperScan("com.naosim.dbtestutil.db")
public class DbTestScanConfiguration {
}

私はMapperScanを書き忘れててハマりました。。お忘れなく

ConfigurationをDIの対象にする

DbTestScanConfigurationを作っただけの場合、ライブラリを使う側がDbTestScanConfigurationへのパスを指定する必要があります。それだと面倒なので、自動的にパスが通るようにします
そのためにspring.factoriesというファイルを作ります

src/main/resources/META-INF/spring.factories

org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.naosim.dbtestutil.DbTestScanConfiguration

これで自動的に読み込まれます

ここまででコード側の修正は終了
最終的なファイル構成はこんな感じです f:id:naosim:20180701164321p:plain

次はgradleの設定

build.gradleでゆるい依存を書く

ゆるいってなんだよ!て感じですが、ホントにゆるい依存を書きます
具体的にはspringとmybatisにcomplieOnlyで依存させます

dependencies {
    compileOnly group: 'org.springframework', name: 'spring-context', version: '5.0.5.RELEASE'
    compileOnly group: 'org.mybatis', name: 'mybatis', version: '3.4.6'
    compileOnly group: 'org.mybatis', name: 'mybatis-spring', version: '1.3.2'
// ...
}

なぜゆるい依存にするか

少しウンチク
なぜゆるい依存にするかというと、このライブラリのせいで使う側のspringやmybatisのバージョンが上がってしまうのを防ぐためです。gradleは依存先で同じライブラリが別のバージョンで依存していた場合に新しい方を採用する仕様なので、私が作ったライブラリが使う側のプロジェクトで使うspring等のバージョンをあげてしまう可能性があります。 ちょっとそれは怖いので。。compileOnlyで逃げます。。 あるべき姿としては、作ったライブラリが動作する最低バージョンを探してそれを指定することなんだろうけど、めんどうなので。。

テスト用の依存を追加する

次はテスト
上記でゆるい依存はしましたがそれでは実行できないので、テストではちゃんと依存を書きます

build.gradle

dependencies {
    compileOnly group: 'org.springframework', name: 'spring-context', version: '5.0.5.RELEASE'
    compileOnly group: 'org.mybatis', name: 'mybatis', version: '3.4.6'
    compileOnly group: 'org.mybatis', name: 'mybatis-spring', version: '1.3.2'

    // test
    testCompile 'org.codehaus.groovy:groovy-all:2.3.11'
    testCompile group: 'junit', name: 'junit', version: '4.12'
    testCompile group: 'org.spockframework', name: 'spock-core', version: '1.1-groovy-2.4'
    testCompile group: 'org.spockframework', name: 'spock-spring', version: '1.1-groovy-2.4'
    // spring
    testCompile group: 'org.springframework', name: 'spring-context', version: '5.0.5.RELEASE'
    testCompile("org.springframework.boot:spring-boot-starter-web:2.0.1.RELEASE")
    testCompile group: 'org.springframework.boot', name: 'spring-boot-starter-test', version: '2.0.0.RELEASE'
    // mybatis
    testCompile group: 'org.mybatis', name: 'mybatis', version: '3.4.6'
    testCompile group: 'org.mybatis.spring.boot', name: 'mybatis-spring-boot-starter', version: '1.3.1'
    testCompile group: 'org.xerial', name: 'sqlite-jdbc', version: '3.21.0.1'
    compileOnly group: 'org.mybatis', name: 'mybatis-spring', version: '1.3.2'

    testCompileOnly group: 'org.projectlombok', name: 'lombok', version: '1.16.20'
}

ぶっちゃけテストは誰にも迷惑かけないのでライブラリをガンガン追加してます。不要なのもあるかも

テストコード側にApplicationクラスを作る

今回はライブラリのためmain側にApplicationクラスがありません。それだとテストができないのでテスト側に作ります
src/test/java/com/naosim/dbtestutil/Application.java ※テスト側ですよ!

package com.naosim.dbtestutil;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class Application {
   public static void main(String[] args) {
       SpringApplication.run(Application.class, args);
   }
}

必要に応じてresourcesも設定する

今回はsqliteを使うのでこんな感じ
src/test/resouces/application.properties

# spring.datasource.driverClassName="org.sqlite.JDBC"
jdbc.driver=org.sqlite.JDBC
spring.datasource.url = jdbc:sqlite:test.db

以上!あとはテストして公開するだけ!
ライブラリをいっぱい作ろう!