Přetěžování core služeb
Mechanismus @ConditionalOnNoCustomService umožňuje v klientském projektu nahradit výchozí core beanu vlastní implementací. Core beana se při přetížení vůbec nezaregistruje — v kontextu vznikne vždy jen jedna instance. Odpadá tak nutnost přetěžovat celou @Configuration třídu pomocí configurationOverride kvůli jedné službě.
Použití v core modulu
Služba, která má být rozšiřitelná, se v @Configuration třídě označí anotací @ConditionalOnNoCustomService:
@ConditionalOnNoCustomService@Beanpublic AbstractCompanyService companyService(CoreDependency dao) { return new DefaultCompanyService(dao);}Anotace automaticky použije název metody (companyService) jako klíč. Pokud je potřeba specifikovat jiný klíč, lze ho předat jako parametr:
@ConditionalOnNoCustomService("myCustomKey")@Beanpublic AbstractCompanyService companyService(CoreDependency dao) { return new DefaultCompanyService(dao);}Použití v klientském projektu
1. Vytvoření properties souboru
V klientském projektu vytvořte soubor src/main/resources/META-INF/edee-custom-services.properties a přidejte název přetěžované beany jako klíč. Jako hodnotu zapište plně kvalifikovaný název nové třídy (implementace vyhodnocuje pouze existenci klíče, ale hodnota slouží pro přehlednost a případné budoucí využití):
# Vypne načtení core beany 'companyService'companyService=com.fg.client.CustomCompanyService2. Definice vlastní beany
V projektu nadefinujte vlastní beanu (klidně se stejným názvem), do které si přes konstruktor nainjektujete projektové závislosti:
@Configurationpublic class ProjectCompanyConfig {
@Bean public AbstractCompanyService companyService( ProjectSpecificDependency projectDep, CoreDependency dao ) { return new ProjectCompanyService(projectDep, dao); }}Protože core beana nebyla díky property souboru vůbec zaregistrována, nedojde k porušení allowBeanDefinitionOverriding=false.
Testování
V JUnit testech stačí na classpath umístit testovací verzi properties souboru:
src/test/resources/META-INF/edee-custom-services.propertiesVýhody oproti @Primary
| Aspekt | @Primary | @ConditionalOnNoCustomService |
|---|---|---|
| Počet instancí v kontextu | Obě (core + klientská) | Pouze klientská |
| Dopad na start a paměť | Zbytečná inicializace core beany | Core beana se vůbec nevytváří |
| Ochrana proti kolizi jmen | Vyžaduje jiné jméno beany | Spolehlivě obchází overriding |
| Složitost pro vývojáře | @Primary + správné pojmenování | Jeden řádek v properties souboru |
Klíčové třídy
com.fg.cps.eshop.cps.config.spring.annotation.ConditionalOnNoCustomService— anotace pro označení výchozích bean metodcom.fg.cps.eshop.cps.config.spring.annotation.NoCustomServiceCondition— evaluátor podmínky
