web-dev-qa-db-fra.com

Comment appliquer l'ordre de chargement des classes de configuration de ressort?

Je travaille avec spring-boot sur un projet multi-modules (maven). Chaque module possède sa propre classe @Configuration. Fondamentalement, j'ai la disposition suivante

Module foo-embedded (s'exécute appelle simplement la méthode 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);
    }
}

Module foo-common (contient tous les beans et la configuration d'initialisation 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
    }
}

Module foo-security (contenant la configuration spring-securiy et les classes de domaine associées), qui a une dépendance maven sur foo-common

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

Lorsque je démarre l'application à l'aide de la classe FooApplication, tout fonctionne comme prévu. Les UserDetailsServiceImpl mentionnés ci-dessus sont câblés automatiquement avec mon UserRepository qui est créé via l'annotation @EnableJpaRepositories.

Depuis que je veux écrire des tests d'intégration, j'ai ajouté un test clss à l'un de mes modules.

Module foo-media (contenant des éléments liés au domaine et des cas de test pour ce module)

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

Lorsque j'exécute le test, il semble que la SecurityConfiguration soit chargée avant le RepositoryConfig.class. Comme la configuration de sécurité a défini UserServiceImpl qui doit être câblé automatiquement, le test ne démarre pas avec un

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

J'ai déjà essayé d'ajouter @DependsOn("UserRepository") à la définition de bean de UserDetailsService, me disant que spring ne peut pas trouver un bean de ce nom.

Tout conseil ou aide serait grandement apprécié! Merci d'avance!

---- MODIFIER (car on m'a demandé de fournir plus de code) ----

Pour les tests, je n'utilise pas le RepositoryConfig.class réel, mais j'ai un TestRepositoryConfig.class dans le module commun. Ressemblant à ceci

@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

J'ai donc pu résoudre ce problème. Comme il l'a souligné, cela n'avait rien à voir avec l'ordre de chargement des classes de configuration (ce qui était ma première pensée).

Comme vous pouvez le remarquer, la seule configuration qui avait un @ComponentScan l'annotation était que FooApplication.class Spring n'était pas en mesure de trouver les référentiels, car il ne savait pas où chercher. Fournir l'attribut basePackages comme ceci:

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

à TestRepositoryConfig.class a fait l'affaire ici.

6
Markus

Vous pouvez utiliser @Order annotation sur vos classes de configuration pour définir l'ordre de chargement. Mais c'est étrange car Spring devrait résoudre le bon ordre - veuillez donc vérifier si votre propriété injecte UserRepository dans UserDetailsService

9
Jakub Kubrynski