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:

java
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:

java
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í):

properties
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:

java
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.properties

Zkopírovat odkaz na sekciVýhody oproti @Primary

Aspekt@Primary@ConditionalOnNoCustomService
Počet instancí v kontextuObě (core + klientská)Pouze klientská
Dopad na start a paměťZbytečná inicializace core beanyCore beana se vůbec nevytváří
Ochrana proti kolizi jmenVyžaduje jiné jméno beanySpolehlivě 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