Přetěžování core služeb
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ě.
Zkopírovat odkaz na sekciPoužití v core modulu
Služba, která má být rozšiřitelná, se v @Configuration třídě označí anotací @ConditionalOnNoCustomService:
1 @ConditionalOnNoCustomService2@Bean3public AbstractCompanyService companyService(CoreDependency dao) {4 return new DefaultCompanyService(dao);5}
Anotace automaticky použije název metody (companyService) jako klíč. Pokud je potřeba specifikovat jiný klíč, lze ho předat jako parametr:
1 @ConditionalOnNoCustomService("myCustomKey")2@Bean3public AbstractCompanyService companyService(CoreDependency dao) {4 return new DefaultCompanyService(dao);5}
Zkopírovat odkaz na sekciPoužití v klientském projektu
Zkopírovat odkaz na sekci1. 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í):
1 # Vypne načtení core beany 'companyService'2companyService=com.fg.client.CustomCompanyService
Zkopírovat odkaz na sekci2. Definice vlastní beany
V projektu nadefinujte vlastní beanu (klidně se stejným názvem), do které si přes konstruktor nainjektujete projektové závislosti:
1 @Configuration2public class ProjectCompanyConfig {3 4 @Bean5 public AbstractCompanyService companyService(6 ProjectSpecificDependency projectDep,7 CoreDependency dao8 ) {9 return new ProjectCompanyService(projectDep, dao);10 }11}
Protože core beana nebyla díky property souboru vůbec zaregistrována, nedojde k porušení allowBeanDefinitionOverriding=false.
Properties soubory se načítají přes PropertiesLoaderUtils.loadAllProperties(), což merguje všechny soubory META-INF/edee-custom-services.properties nalezené na classpath (napříč JARy). Každý modul nebo klientský projekt tak může deklarovat své přetížení nezávisle.
Zkopírovat odkaz na sekciTestování
V JUnit testech stačí na classpath umístit testovací verzi properties souboru:
1 src/test/resources/META-INF/edee-custom-services.propertiesZkopírovat odkaz na sekciVý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 |
Zkopírovat odkaz na sekciKlíčové třídy
- com.fg.cps.eshop.cps.config.spring.annotation.ConditionalOnNoCustomService — anotace pro označení výchozích bean metod
- com.fg.cps.eshop.cps.config.spring.annotation.NoCustomServiceCondition — evaluátor podmínky