Подтвердить что ты не робот

Как обеспечить порядок загрузки классов конфигурации spring?

Я работаю с spring -boot в проекте с несколькими модулями (maven). Каждый модуль имеет собственный класс @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 (содержит все конфигурации инициализации beans и 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-security (содержащий конфигурацию spring -securiy и связанные классы домена), которая имеет зависимость maven от foo-common

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

Когда я запускаю приложение, используя класс FooApplication, все работает так, как ожидалось. Вышеупомянутый UserDetailsServiceImpl получает autwired с моим UserRepository, который создается через аннотацию @EnableJpaRepositories.

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

Модуль foo-media (содержащий некоторые связанные с доменом материалы плюс тестовые примеры для этого модуля)

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

Когда я запускаю тест, кажется, что SecurityConfiguration загружается до того, как RepositoryConfig.class делает. Поскольку в конфиге безопасности определен UserServiceImpl, который должен быть автообновлен, тест не запускается с

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

Я уже пытался добавить @DependsOn("UserRepository") в определение bean UserDetailsService, сообщив, что 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
    }
}
4b9b3361

Ответ 1

Так что я смог решить это. Как он отметил, это не имеет никакого отношения к порядку загрузки классов конфигурации (это была моя первая мысль).

Как вы можете заметить, единственной конфигурацией, в которой была аннотация @ComponentScan, была FooApplication.class Spring не смог найти Хранилища, поскольку он не знал, где искать. Предоставление атрибута basePackages следующим образом:

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

в TestRepositoryConfig.class сделал трюк здесь.

Ответ 2

Вы можете использовать аннотацию @Order в ваших классах конфигурации для определения порядка загрузки. Но это странно, потому что Spring должен разрешить правильный порядок - поэтому, пожалуйста, проверьте, если вы добавляете свойство UserRepository в UserDetailsService