Mercurial > hg > SpringPlayground
changeset 0:64e2ebad3366
Import des plain Spring DI playground
line wrap: on
line diff
--- /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
--- /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 @@ +<project xmlns="http://maven.apache.org/POM/4.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + <groupId>de.comline</groupId> + <artifactId>spring-di-playground</artifactId> + <version>0.0.1-SNAPSHOT</version> + <name>Spring DI container playground</name> + + <properties> + <jdk.version.source>1.8</jdk.version.source> + <jdk.version.target>1.8</jdk.version.target> + </properties> + + <build> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-compiler-plugin</artifactId> + <version>3.8.1</version> + <configuration> + <verbose>true</verbose> + <source>${jdk.version.source}</source> + <target>${jdk.version.target}</target> + </configuration> + </plugin> + </plugins> + </build> + + <dependencies> + <dependency> + <groupId>org.springframework</groupId> + <artifactId>spring-context</artifactId> + <version>5.1.14.RELEASE</version> + </dependency> + + <dependency> + <groupId>org.junit.jupiter</groupId> + <artifactId>junit-jupiter</artifactId> + <version>5.6.2</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.hamcrest</groupId> + <artifactId>hamcrest</artifactId> + <version>2.2</version> + <scope>test</scope> + </dependency> + </dependencies> +</project> \ No newline at end of file
--- /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.<br/> + * 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(); + } + } +}
--- /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(); + } + } +}
--- /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
--- /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"; + } +}
--- /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"; + } +}
--- /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"; + } +}
--- /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(); +}
--- /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 { +}
--- /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 { +}