# HG changeset patch # User Dirk Olmes # Date 1597154744 -7200 # Node ID 64e2ebad33667a83d9bedfe669d0df3ecd68d631 Import des plain Spring DI playground diff -r 000000000000 -r 64e2ebad3366 .hgignore --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/.hgignore Tue Aug 11 16:05:44 2020 +0200 @@ -0,0 +1,4 @@ +.classpath +.project +.settings +target diff -r 000000000000 -r 64e2ebad3366 spring-di-playground/pom.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/spring-di-playground/pom.xml Tue Aug 11 16:05:44 2020 +0200 @@ -0,0 +1,50 @@ + + 4.0.0 + de.comline + spring-di-playground + 0.0.1-SNAPSHOT + Spring DI container playground + + + 1.8 + 1.8 + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.8.1 + + true + ${jdk.version.source} + ${jdk.version.target} + + + + + + + + org.springframework + spring-context + 5.1.14.RELEASE + + + + org.junit.jupiter + junit-jupiter + 5.6.2 + test + + + org.hamcrest + hamcrest + 2.2 + test + + + \ No newline at end of file diff -r 000000000000 -r 64e2ebad3366 spring-di-playground/src/test/java/de/comline/spring/ClasspathScanningTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/spring-di-playground/src/test/java/de/comline/spring/ClasspathScanningTest.java Tue Aug 11 16:05:44 2020 +0200 @@ -0,0 +1,74 @@ +package de.comline.spring; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.is; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.fail; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.NoUniqueBeanDefinitionException; +import org.springframework.context.annotation.AnnotationConfigApplicationContext; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.ComponentScan.Filter; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.FilterType; + +import de.comline.spring.model.MovieCatalog; +import de.comline.spring.model.scanning.ActionMovieCatalogComponent; + +public class ClasspathScanningTest { + @Test + @DisplayName("Scanning explicit packages") + public void classpathScanning() { + try (AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext("de.comline.spring.model.scanning")) { + assertThrows(NoUniqueBeanDefinitionException.class, () -> { + context.getBean(MovieCatalog.class); + fail("Classpath scanning must have detected both implementations of the MovieCatalog interface"); + }); + } + } + + @Test + @DisplayName("Scanning by configuration") + public void explicitConfiguration() { + try (AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ScanningConfiguration.class)) { + assertThrows(NoUniqueBeanDefinitionException.class, () -> { + context.getBean(MovieCatalog.class); + fail("Classpath scanning must have detected both implementations of the MovieCatalog interface"); + }); + } + } + + @Test + @DisplayName("Scanning by configuration with filter") + public void configurationWithFilter() { + try (AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(FilteredScanningConfiguration.class)) { + MovieCatalog catalog = context.getBean(MovieCatalog.class); + assertThat(catalog.getCategory(), is("Comedy")); + } + } + + /** + * Note: class may not be final.
+ * Note: class must have a default constructor which is package protected at + * least + */ + @Configuration + @ComponentScan(basePackages = "de.comline.spring.model.scanning") + private static class ScanningConfiguration { + @SuppressWarnings("unused") + ScanningConfiguration() { + super(); + } + } + + @Configuration + @ComponentScan(basePackages = "de.comline.spring.model.scanning", excludeFilters = @Filter(type = FilterType.ASSIGNABLE_TYPE, classes = ActionMovieCatalogComponent.class)) + private static class FilteredScanningConfiguration { + @SuppressWarnings("unused") + FilteredScanningConfiguration() { + super(); + } + } +} diff -r 000000000000 -r 64e2ebad3366 spring-di-playground/src/test/java/de/comline/spring/ConfigurationTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/spring-di-playground/src/test/java/de/comline/spring/ConfigurationTest.java Tue Aug 11 16:05:44 2020 +0200 @@ -0,0 +1,64 @@ +package de.comline.spring; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.is; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.fail; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.NoUniqueBeanDefinitionException; +import org.springframework.context.annotation.AnnotationConfigApplicationContext; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import de.comline.spring.model.ActionMovieCatalog; +import de.comline.spring.model.ComedyMovieCatalog; +import de.comline.spring.model.MovieCatalog; + +public class ConfigurationTest { + @Test + @DisplayName("Explicit bean configuration") + public void beansInConfiguration() { + try (AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(BeansConfiguration.class)) { + MovieCatalog catalog = context.getBean(MovieCatalog.class); + assertThat(catalog.getCategory(), is("Comedy")); + } + } + + @Test + @DisplayName("Duplicate beans can be registered") + public void duplicateBeansInConfiguration() { + try (AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(DuplicateBeansConfiguration.class)) { + assertThrows(NoUniqueBeanDefinitionException.class, () -> { + context.getBean(MovieCatalog.class); + fail("Configuration scanning must have detected both implementations of the MovieCatalog interface"); + }); + } + } + + @Configuration + private static class BeansConfiguration { + BeansConfiguration() { + super(); + } + + @Bean + MovieCatalog defineMovieCatalog() { + return new ComedyMovieCatalog(); + } + } + + @Configuration + private static class DuplicateBeansConfiguration extends BeansConfiguration { + @SuppressWarnings("unused") + DuplicateBeansConfiguration() { + super(); + } + + @Bean + MovieCatalog duplicateMovieCatalog() { + return new ActionMovieCatalog(); + } + } +} diff -r 000000000000 -r 64e2ebad3366 spring-di-playground/src/test/java/de/comline/spring/QualifierTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/spring-di-playground/src/test/java/de/comline/spring/QualifierTest.java Tue Aug 11 16:05:44 2020 +0200 @@ -0,0 +1,57 @@ +package de.comline.spring; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.containsString; +import static org.hamcrest.Matchers.is; +import static org.junit.jupiter.api.Assertions.assertThrows; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.NoUniqueBeanDefinitionException; +import org.springframework.context.ConfigurableApplicationContext; +import org.springframework.context.annotation.AnnotationConfigApplicationContext; + +import de.comline.spring.model.ActionMovieCatalog; +import de.comline.spring.model.ActionMovieLister; +import de.comline.spring.model.ComedyMovieCatalog; +import de.comline.spring.model.MovieCatalog; + +public class QualifierTest { + @Test + @DisplayName("Requesting explicit interface type") + public void explicitType() { + try (ConfigurableApplicationContext context = new AnnotationConfigApplicationContext(ActionMovieCatalog.class, ComedyMovieCatalog.class)) { + MovieCatalog action = context.getBean(ActionMovieCatalog.class); + assertThat(action.getCategory(), is("Action")); + } + } + + @Test + @DisplayName("Qualifier can be specified at source") + public void qualifierAtSource() { + // Note how we add multiple interface implementations to the context + try (ConfigurableApplicationContext context = new AnnotationConfigApplicationContext(ActionMovieCatalog.class, ComedyMovieCatalog.class, ActionMovieLister.class)) { + ActionMovieLister lister = context.getBean(ActionMovieLister.class); + assertThat(lister.toString(), containsString("Action")); + } + } + + @Test + @DisplayName("Binding only a single interface implementation") + public void singleImplementationOfInterface() { + try (ConfigurableApplicationContext context = new AnnotationConfigApplicationContext(ComedyMovieCatalog.class)) { + MovieCatalog catalog = context.getBean(MovieCatalog.class); + assertThat(catalog.getCategory(), is("Comedy")); + } + } + + @Test + @DisplayName("Multiple implementations of the same interface cannot be injected") + public void multipleInterfaceImplementations() { + try (ConfigurableApplicationContext context = new AnnotationConfigApplicationContext(ActionMovieCatalog.class, ComedyMovieCatalog.class)) { + assertThrows(NoUniqueBeanDefinitionException.class, () -> { + context.getBean(MovieCatalog.class); + }); + } + } +} \ No newline at end of file diff -r 000000000000 -r 64e2ebad3366 spring-di-playground/src/test/java/de/comline/spring/model/ActionMovieCatalog.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/spring-di-playground/src/test/java/de/comline/spring/model/ActionMovieCatalog.java Tue Aug 11 16:05:44 2020 +0200 @@ -0,0 +1,11 @@ +package de.comline.spring.model; + +import org.springframework.beans.factory.annotation.Qualifier; + +@Qualifier(value = "Action") +public class ActionMovieCatalog implements MovieCatalog { + @Override + public String getCategory() { + return "Action"; + } +} diff -r 000000000000 -r 64e2ebad3366 spring-di-playground/src/test/java/de/comline/spring/model/ActionMovieLister.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/spring-di-playground/src/test/java/de/comline/spring/model/ActionMovieLister.java Tue Aug 11 16:05:44 2020 +0200 @@ -0,0 +1,20 @@ +package de.comline.spring.model; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; + +public class ActionMovieLister { + /** + * The qualifier is specified at the source - which is almost never what you + * want. Note however, how the qualifier mentioned here matches the qualifier + * annotation value on the injected class (ActionMovieCatalog). + */ + @Autowired + @Qualifier(value = "Action") + private MovieCatalog actionMovies; + + @Override + public String toString() { + return "Listing of " + actionMovies.getCategory() + " films"; + } +} diff -r 000000000000 -r 64e2ebad3366 spring-di-playground/src/test/java/de/comline/spring/model/ComedyMovieCatalog.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/spring-di-playground/src/test/java/de/comline/spring/model/ComedyMovieCatalog.java Tue Aug 11 16:05:44 2020 +0200 @@ -0,0 +1,11 @@ +package de.comline.spring.model; + +import org.springframework.beans.factory.annotation.Qualifier; + +@Qualifier(value = "Comedy") +public class ComedyMovieCatalog implements MovieCatalog { + @Override + public String getCategory() { + return "Comedy"; + } +} diff -r 000000000000 -r 64e2ebad3366 spring-di-playground/src/test/java/de/comline/spring/model/MovieCatalog.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/spring-di-playground/src/test/java/de/comline/spring/model/MovieCatalog.java Tue Aug 11 16:05:44 2020 +0200 @@ -0,0 +1,5 @@ +package de.comline.spring.model; + +public interface MovieCatalog { + public String getCategory(); +} diff -r 000000000000 -r 64e2ebad3366 spring-di-playground/src/test/java/de/comline/spring/model/scanning/ActionMovieCatalogComponent.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/spring-di-playground/src/test/java/de/comline/spring/model/scanning/ActionMovieCatalogComponent.java Tue Aug 11 16:05:44 2020 +0200 @@ -0,0 +1,9 @@ +package de.comline.spring.model.scanning; + +import org.springframework.stereotype.Component; + +import de.comline.spring.model.ActionMovieCatalog; + +@Component +public class ActionMovieCatalogComponent extends ActionMovieCatalog { +} diff -r 000000000000 -r 64e2ebad3366 spring-di-playground/src/test/java/de/comline/spring/model/scanning/ComedyMovieCatalogComponent.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/spring-di-playground/src/test/java/de/comline/spring/model/scanning/ComedyMovieCatalogComponent.java Tue Aug 11 16:05:44 2020 +0200 @@ -0,0 +1,9 @@ +package de.comline.spring.model.scanning; + +import org.springframework.stereotype.Component; + +import de.comline.spring.model.ComedyMovieCatalog; + +@Component +public class ComedyMovieCatalogComponent extends ComedyMovieCatalog { +}