web-dev-qa-db-ja.com

Spring構成クラスのロード順を強制するにはどうすればよいですか?

マルチモジュールプロジェクト(maven)でspring-bootを使用しています。各モジュールには、独自の@Configurationクラスがあります。基本的に私は次のレイアウトを持っています

モジュールfoo-embedded(実行はSpringApplication.run()を呼び出すだけです)メソッド:

_@Configuration
@EnableAutoConfiguration
@ComponentScan("de.foobar.rootpackage")
@Import({ApplicationConfig.class, RepositoryConfig.class, SecurityConfig.class})
public class FooApplication {

    public static void main(String[] args) throws Exception {
        SpringApplication.run(FooApplication.class, args);
    }
}
_

モジュールfoo-common(すべてのBeanとspring-data-jpa初期化構成が含まれます)

_@Configuration
@EnableJpaRepositories
@EnableTransactionManagement(entityManagerFactoryRef="entityManagerFactory")
public class RepositoryConfig {

    @Bean(destroyMethod = "shutdown")
    public DataSource getDataSource() {
        // returning a Hikari CP here
    }

    @Bean(name = "entityManagerFactory") // overriding spring boots default
    public EntityManagerFactory getEntityManagerFactory() {
        // returning a new LocalEntityManagerFactoryBean here
    }
}
_

Foo-commonへのMaven依存関係を持つモジュールfoo-security(spring-securiy構成と関連ドメインクラスを含む)

_@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    // configuring HTTP security and defining my UserDetailsService Bean
}
_

FooApplicationクラスを使用してアプリケーションを起動すると、すべてが期待どおりに機能します。上記のUserDetailsS​​erviceImplは、@ EnableJpaRepositoriesアノテーションを介して作成されているUserRepositoryと自動接続されます。

いくつかの統合テストを書きたいので、モジュールの1つにテストクラスを追加しました。

モジュールfoo-media(ドメイン関連のものとそのモジュールのテストケースを含む)

_@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = {RepositoryConfig.class, SecurityConfig.class})
@WebAppConfiguration
@IntegrationTest
public class DirectoryIntegrationTest {
    // my test code
}
_

テストを実行すると、RepositoryConfig.classが実行される前にSecurityConfigurationがロードされるようです。セキュリティ構成は、自動配線する必要があるUserServiceImplを定義しているため、テストは、

_NoSuchBeanDefinitionException telling me: No qualifying bean of type [com.foo.rootpackage.security.repository.UserRepository]
_

UserDetailsServiceのBean定義に@DependsOn("UserRepository")を追加しようとしましたが、その名前ではSpringがBeanを見つけられないことを教えてくれました。

ヒントやヘルプは大歓迎です!前もって感謝します!

---- [〜#〜] edit [〜#〜](コードの追加を求められたため)----

テストでは、実際のRepositoryConfig.classを使用しませんが、共通モジュールにTestRepositoryConfig.classがあります。こんな感じ

_@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(entityManagerFactoryRef = "entityManagerFactory", basePackages = "de.foobar.rootpackage")
public class TestRepositoryConfig extends RepositoryConfig {

    @Bean
    @Override
    public DataSource getDataSource() {
        // returning the ds for testing
    }
}
_
21
Markus

だから私はこれを解決することができました。それが指摘したように、それは構成クラスのロード順序とは何の関係もありませんでした(これは私の最初の考えでした)。

お気づきかもしれませんが、@ComponentScanアノテーションは、FooApplication.classであり、Springはリポジトリを見つけることができませんでした。どこを探すべきかわからなかったためです。次のようにbasePackages属性を提供します。

@EnableJpaRepositories(basePackages = "de.foobar.rootpackage")

testRepositoryConfig.classでこのトリックを行いました。

6
Markus

構成クラスで@Order注釈を使用して、ロード順序を定義できます。しかし、Springは適切な順序を解決する必要があるため、奇妙です。したがって、UserRepository in UserDetailsService

9
Jakub Kubrynski