├── .github └── workflows │ ├── maven.yml │ └── push.yml ├── .gitignore ├── .mvn ├── settings.xml └── wrapper │ ├── maven-wrapper.jar │ └── maven-wrapper.properties ├── .springjavaformatconfig ├── LICENSE.txt ├── README.md ├── config └── checkstyle │ └── checkstyle.xml ├── mvnw ├── mvnw.cmd ├── pom.xml └── src ├── main ├── java │ └── org │ │ └── springframework │ │ └── guice │ │ ├── annotation │ │ ├── EnableGuiceModules.java │ │ ├── GuiceFactoryBean.java │ │ ├── GuiceModule.java │ │ ├── GuiceModuleRegistrar.java │ │ ├── InjectorFactory.java │ │ ├── ModuleFilter.java │ │ └── ModuleRegistryConfiguration.java │ │ ├── injector │ │ └── SpringInjector.java │ │ └── module │ │ ├── BeanFactoryProvider.java │ │ ├── BindingTypeMatcher.java │ │ ├── GuiceAutowireCandidateResolver.java │ │ ├── GuiceModuleMetadata.java │ │ └── SpringModule.java └── resources │ └── META-INF │ └── additional-spring-configuration-metadata.json └── test └── java └── org └── springframework └── guice ├── AbstractCompleteWiringTests.java ├── AdhocTestSuite.java ├── BeanPostProcessorTests.java ├── BindingAnnotationTests.java ├── BindingDeduplicationTests.java ├── DuplicateNamesDifferentTypesTests.java ├── ElementVisitorTests.java ├── GuiceWiringTests.java ├── InjectorFactoryTests.java ├── JustInTimeBindingTests.java ├── LazyInitializationTests.java ├── MapBindingDeduplicationTests.java ├── MapWiringTests.java ├── ModuleFilteringTests.java ├── NativeGuiceTests.java ├── PartialInjectionTests.java ├── PrivateModuleTests.java ├── PrototypeScopedBeanTests.java ├── ProvidesSupplierWiringTests.java ├── ScopingTests.java ├── SetBindingTests.java ├── SimpleWiringTests.java ├── SpringAutowiredCollectionTests.java ├── SuperClassTests.java ├── annotation ├── EnableGuiceModulesTests.java ├── GuiceModuleAnnotationGenericTypeTests.java ├── GuiceModuleAnnotationTests.java ├── ModuleBeanWiringTests.java └── ModuleNamedBeanWiringTests.java ├── injector ├── SpringInjectorTests.java └── SpringWiringTests.java └── module ├── DevelepmentStageInjectorTest.java ├── SpringModuleGuiceBindingAwareTests.java ├── SpringModuleMetadataTests.java ├── SpringModuleWiringTests.java └── SpringModuleWrappedTests.java /.github/workflows/maven.yml: -------------------------------------------------------------------------------- 1 | # This workflow will build a Java project with Maven, and cache/restore any dependencies to improve the workflow execution time 2 | # For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-maven 3 | 4 | name: Java CI with Maven 5 | 6 | on: 7 | pull_request: 8 | branches: [ main ] 9 | 10 | jobs: 11 | build: 12 | name: Build Pull Request 13 | 14 | runs-on: ubuntu-latest 15 | if: ${{ github.repository == 'spring-projects/spring-guice' }} 16 | 17 | steps: 18 | - uses: actions/checkout@v4 19 | - name: Set up JDK 17 20 | uses: actions/setup-java@v4 21 | with: 22 | java-version: '17' 23 | distribution: 'temurin' 24 | cache: maven 25 | - name: Build with Maven 26 | run: ./mvnw -B package 27 | 28 | -------------------------------------------------------------------------------- /.github/workflows/push.yml: -------------------------------------------------------------------------------- 1 | # This workflow will build a Java project with Maven, and cache/restore any dependencies to improve the workflow execution time 2 | # For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-maven 3 | 4 | name: Java CI with Maven Deploy 5 | 6 | on: 7 | push: 8 | branches: [ main ] 9 | 10 | jobs: 11 | build: 12 | name: Build and Deploy On Push 13 | 14 | runs-on: ubuntu-latest 15 | if: ${{ github.repository == 'spring-projects/spring-guice' }} 16 | 17 | steps: 18 | - uses: actions/checkout@v4 19 | - name: Set up JDK 17 20 | uses: actions/setup-java@v4 21 | with: 22 | java-version: '17' 23 | distribution: 'temurin' 24 | cache: maven 25 | - name: Deploy with Maven 26 | env: 27 | spring_username: ${{ secrets.ARTIFACTORY_USERNAME }} 28 | spring_password: ${{ secrets.ARTIFACTORY_PASSWORD }} 29 | sonatype_username: ${{ secrets.OSSRH_S01_TOKEN_USERNAME }} 30 | sonatype_password: ${{ secrets.OSSRH_S01_TOKEN_PASSWORD }} 31 | signing_key: ${{ secrets.GPG_PRIVATE_KEY }} 32 | passphrase: ${{ secrets.GPG_PASSPHRASE }} 33 | run: | 34 | echo "${signing_key}" > private.asc 35 | gpg --import --batch --no-tty private.asc 36 | ./mvnw -B deploy -s .mvn/settings.xml 37 | 38 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | #*# 2 | .#* 3 | *~ 4 | _site/ 5 | */src/META-INF/ 6 | */src/main/java/META-INF/ 7 | bin/ 8 | target/ 9 | .classpath 10 | .project 11 | .DS_Store 12 | .settings/ 13 | .springBeans 14 | .sts4-cache/ 15 | .vscode/ 16 | *.iml 17 | *.iws 18 | *.ipr 19 | .idea/ 20 | credentials.yml 21 | -------------------------------------------------------------------------------- /.mvn/settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | release 6 | 7 | true 8 | 9 | 10 | ${env.passphrase} 11 | 12 | 13 | 14 | 15 | 16 | sonatype-nexus-staging 17 | ${env.sonatype_username} 18 | ${env.sonatype_password} 19 | 20 | 21 | repo.spring.io 22 | ${env.spring_username} 23 | ${env.spring_password} 24 | 25 | 26 | spring-libs-milestones 27 | ${env.spring_username} 28 | ${env.spring_password} 29 | 30 | 31 | spring-libs-snapshots 32 | ${env.spring_username} 33 | ${env.spring_password} 34 | 35 | 36 | spring-libs-releases 37 | ${env.spring_username} 38 | ${env.spring_password} 39 | 40 | 41 | spring-libs-plugins 42 | ${env.spring_username} 43 | ${env.spring_password} 44 | 45 | 46 | -------------------------------------------------------------------------------- /.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spring-projects/spring-guice/498fed04ab900b57237dda9936e41b95c4750303/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo1.maven.org/maven2/org/apache/maven/apache-maven/3.5.4/apache-maven-3.5.4-bin.zip 2 | -------------------------------------------------------------------------------- /.springjavaformatconfig: -------------------------------------------------------------------------------- 1 | java-baseline=8 -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | This project provides bridges between Spring and Guice so that you can 2 | use one from the other (and vice versa). It works with Spring 6 (or at least the tests are green), but Guice does [not support the Jakarta annotations](https://github.com/google/guice/issues/1383) so it may break in unexpected ways. 3 | 4 | ![Build Status](https://travis-ci.org/spring-projects/spring-guice.svg?branch=master) 5 | 6 | ## Using a Spring ApplicationContext as a Module in Guice 7 | 8 | The main bridge in this case is a Guice `Module` that wraps an 9 | existing Spring `ApplicationContext`. Example: 10 | 11 | ```java 12 | AnnotationConfigApplicationContext context = 13 | new AnnotationConfigApplicationContext(ApplicationConfiguration.class); 14 | Injector injector = Guice.createInjector(new SpringModule(context), new MyModule()); 15 | Service service = injector.getInstance(Service.class); 16 | ``` 17 | 18 | `SpringModule` (`org.springframework.guice.module.SpringModule`) will wrap the existing spring configurations for you. 19 | 20 | Note that the `ApplicationContext` in this example might contain the 21 | `Service` definition or it might be in the Guice `Module` 22 | (`MyModule`), or if `Service` is a concrete class it could be neither, 23 | but Guice creates an instance and wires it for us. 24 | 25 | If the `ApplicationConfiguration` is annotated `@GuiceModule` then it 26 | can filter the types of bean that are registered with the Guice 27 | binder. Example: 28 | 29 | ```java 30 | @Configuration 31 | @GuiceModule(includeFilters=@Filter(pattern=.*\\.Service)) 32 | public class ApplicationConfiguration { 33 | @Bean 34 | public MyService service() { 35 | ... 36 | } 37 | } 38 | ``` 39 | 40 | In this case, only bean types (or interfaces) called "Service" will 41 | match the include filter, and only those beans will be bound. 42 | 43 | If there are multiple `@Beans` of the same type in the 44 | `ApplicationContext` then the `SpringModule` will register them all, 45 | and there will be a runtime exception if an `Injector` needs one. As 46 | with normal Spring dependency resolution, you can add the `@Primary` 47 | marker to a single bean to differentiate and hint to the `Injector` 48 | which instance to use. 49 | 50 | ## Registering Spring Configuration Classes as a Guice Module 51 | 52 | If your Spring `@Configuration` has dependencies that can only come 53 | from a Guice `Module` and you prefer to use the Guice APIs to build up 54 | the configuration (so you can't use `@EnableGuiceModules` below), then 55 | you can create a `SpringModule` from a 56 | `Provider` instead of from an 57 | existing `ApplicationContext`. There are some additional features that 58 | may also apply: 59 | 60 | * If the bean factory created by the provider is a 61 | `DefaultListableBeanFactory` (mostly it would be if it came from an 62 | `ApplicationContext`), then it will pick up a special Guice-aware 63 | `AutowireCandidateResolver`, meaning that it will be able to inject 64 | dependencies from Guice modules that are not registered as beans. 65 | 66 | * If the bean factory contains any beans of type `ProvisionListener` 67 | (a Guice lifecysle listener), then those will be instantiated and 68 | registered with Guice. 69 | 70 | To take advantage of the autowiring the bean factory must come from an 71 | `ApplicationContext` that is not fully refreshed (refreshing would 72 | resolve all the dependencies and fail because the Guice resolver is 73 | not yet registered). To help you build bean factories that have this 74 | quality there is a convenience class called `BeanFactoryProvider` with 75 | static methods which you can use to create a provider to inject into a 76 | `SpringModule`. Example: 77 | 78 | ```java 79 | Injector injector = Guice.createInjector(new SimpleGuiceModule(), 80 | new SpringModule(BeanFactoryProvider.from(SpringConfiguration.class))); 81 | ``` 82 | 83 | The `SimpleGuiceModule` contains a component that the 84 | `SpringConfiguration` depends on. 85 | 86 | ## Using existing Guice Modules in a Spring ApplicationContext 87 | 88 | The main feature here is a Spring `@Configuration` annotation: 89 | `@EnableGuiceModules`. If you have Guice `Modules` that you want to 90 | re-use (e.g. if they come from a third party) you can declare them in 91 | a Spring `ApplicationContext` as `@Beans`, and expose all their 92 | bindings. Example: 93 | 94 | ```java 95 | @EnableGuiceModules 96 | @Configuration 97 | public static class TestConfig { 98 | 99 | @Bean 100 | public static MyModule myModule() { 101 | return new MyModule(); 102 | } 103 | 104 | @Bean 105 | public Spam spam(Service service) { 106 | return new Spam(service); 107 | } 108 | 109 | } 110 | ``` 111 | 112 | The `Service` was defined in the Guice module `MyModule`, and then it 113 | was be bound to the autowired `spam()` method when Spring started. 114 | 115 | ### Filtering out modules from startup of ApplicationContext 116 | 117 | In certain cases you might need to ensure that some modules are not configured at all, even though they will be absent from the final `ApplicationContext`. 118 | This might be due to external code that may be hard to change that causes side effects at binding time, for example. 119 | To ensure that these modules are not called at all you can define one or more`ModuleFilter` beans that will be applied to filter out modules from the context before they are touched by the Spring-Guice bridge. 120 | 121 | ```java 122 | 123 | import org.springframework.context.annotation.Bean; 124 | import org.springframework.guice.annotation.ModuleFilter; 125 | 126 | public static class TestConfig { 127 | 128 | 129 | @Bean 130 | public static MyModule myModule() { 131 | return new MyModule(); 132 | } 133 | 134 | @Bean 135 | public ModuleFilter myFilter() { 136 | return module -> !(module instanceof MyModule); 137 | } 138 | } 139 | 140 | ``` 141 | This will ensure that no `configure()` methods are called on the filtered modules. 142 | 143 | ## Configuration Class Enhancements 144 | 145 | Note that the `Module` bean definition in the example above is 146 | declared in a `static` method. This is intentional and can be used to 147 | avoid accidentally preventing Spring from being able to enhance the 148 | parent `@Configuration` class. The default behaviour for Spring is to 149 | create a proxy for `@Configuration` classes so the `@Bean` methods 150 | can call each other and Spring will preserve the singleton nature of 151 | the bean factory - one bean of each type per bean id. 152 | 153 | If you see logs like this when the context starts: 154 | 155 | ``` 156 | Mar 21, 2022 8:30:35 AM org.springframework.context.annotation.ConfigurationClassPostProcessor enhanceConfigurationClasses 157 | INFO: Cannot enhance @Configuration bean definition 'TestConfig' since its singleton instance has been created too early. The typical cause is a non-static @Bean method with a BeanDefinitionRegistryPostProcessor return type: Consider declaring such methods as 'static'. 158 | ``` 159 | 160 | that is a sign that you might want to use static methods to define 161 | any beans of type `Module`. It is logged at INFO because Spring 162 | doesn't know if it was intentional or not. Most likely it was 163 | unintentional, and it is better to avoid nasty surprises later 164 | if we can. 165 | 166 | Another way to avoid the warning is to declare the parent class as 167 | `@Configuration(proxyBeanMethods = false)` so that Spring knows that 168 | you don't even want to enhance the class. It's not a bad idea to use 169 | that flag wherever you can because it saves some time on start up 170 | if the proxy doesn't need to be created. 171 | 172 | ## Using Guice as an API for accessing a Spring ApplicationContext 173 | 174 | In this case the main feature is an `Injector` implementation that 175 | wraps a Spring `ApplicationContext`. Example: 176 | 177 | ```java 178 | AnnotationConfigApplicationContext context = 179 | new AnnotationConfigApplicationContext(ApplicationConfiguration.class); 180 | Injector injector = new SpringInjector(context); 181 | Service service = injector.getInstance(Service.class); 182 | ``` 183 | 184 | If there is a `@Bean` of type `Service` it will be returned from the 185 | `Injector`. But there may actually not be a `@Bean` definition of type 186 | `Service`, and if it is a concrete type then the `Injector` will 187 | create it and autowire its dependencies for you. A side effect of this 188 | is that a `BeanDefinition` *will* be created. 189 | 190 | In the example above, if `ApplicationConfiguration` was annotated 191 | `@EnableGuiceModules` then there is an `Injector` bean already waiting 192 | to be used, including wiring it into the application itself if you 193 | need it. So this works as well: 194 | 195 | ```java 196 | @Configuration 197 | @EnableGuiceModules 198 | public class ApplicationConfiguration { 199 | 200 | @Autowired 201 | private Injector injector; 202 | 203 | @Bean 204 | public Foo foo() { 205 | // Guice creates and does the wiring of Foo instead of Spring 206 | return injector.getInstance(Foo.class); 207 | } 208 | } 209 | ``` 210 | 211 | In this example if the `Injector` has a binding for a `Provider` of 212 | `Foo.class` then the `foo()` method is redundant - it is already 213 | resolvable as a Spring dependency. But if Guice is being used as a 214 | factory for new objects that it doesn't have bindings for, then it 215 | makes sense. 216 | 217 | **Note:** if you also have `@GuiceModule` in your context, then using 218 | the injector to create a `@Bean` directly is a bad idea (there's a 219 | dependency cycle). You *can* do it, and break the cycle, if you 220 | exclude the `@Bean` type from the `Injector` bindings using the 221 | `@GuiceModule` exclude filters. 222 | 223 | ## Configurable Options 224 | 225 | For a full list of configuration options, see the [configuration metadata file](https://github.com/spring-projects/spring-guice/blob/master/src/main/resources/META-INF/additional-spring-configuration-metadata.json). 226 | 227 | **Binding Deduplication** - When using `@EnableGuiceModules`, if a Spring `Bean` and a Guice `Binding` both exist for the same type and `Qualifier`, creation of the `Injector` will fail. You may instead prefer to keep Spring's instance of the type instead of receiving this error. To accomplish this, you may set the property `spring.guice.dedup=true`. 228 | 229 | **Disable Guice just-in-time bindings** - When enabled (default enabled), beans without explicit definitions will be created using Guice just-in-time bindings. Otherwise, it will fail with UnsatisfiedDependencyException. To disable, set the property `spring.guice.autowireJIT=false`. 230 | 231 | ## Limitations 232 | 233 | * So far there is no support for the Guice SPI methods in 234 | `SpringInjector` so tooling may not work. It wouldn't be hard to do. 235 | 236 | * `SpringInjector` only knows about raw types and bean names, so it 237 | ignores additional meta-information in factory requests (like 238 | annotations other than `@Named`). Should be easy enough to fix, but 239 | some compromises might have to be made. 240 | 241 | * `SpringInjector` has no support for creating child or parent 242 | `Injectors`. Probably not difficult. 243 | 244 | * `SpringModule` treats all beans as singletons. 245 | 246 | * `SpringModule` binds all interfaces and all names of a bean it can 247 | find. This should work out OK, as long as those interfaces are not 248 | needed for injection (and if there is no `@Primary` bean). 249 | -------------------------------------------------------------------------------- /config/checkstyle/checkstyle.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /mvnw: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # ---------------------------------------------------------------------------- 3 | # Licensed to the Apache Software Foundation (ASF) under one 4 | # or more contributor license agreements. See the NOTICE file 5 | # distributed with this work for additional information 6 | # regarding copyright ownership. The ASF licenses this file 7 | # to you under the Apache License, Version 2.0 (the 8 | # "License"); you may not use this file except in compliance 9 | # with the License. You may obtain a copy of the License at 10 | # 11 | # https://www.apache.org/licenses/LICENSE-2.0 12 | # 13 | # Unless required by applicable law or agreed to in writing, 14 | # software distributed under the License is distributed on an 15 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 | # KIND, either express or implied. See the License for the 17 | # specific language governing permissions and limitations 18 | # under the License. 19 | # ---------------------------------------------------------------------------- 20 | 21 | # ---------------------------------------------------------------------------- 22 | # Maven2 Start Up Batch script 23 | # 24 | # Required ENV vars: 25 | # ------------------ 26 | # JAVA_HOME - location of a JDK home dir 27 | # 28 | # Optional ENV vars 29 | # ----------------- 30 | # M2_HOME - location of maven2's installed home dir 31 | # MAVEN_OPTS - parameters passed to the Java VM when running Maven 32 | # e.g. to debug Maven itself, use 33 | # set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 34 | # MAVEN_SKIP_RC - flag to disable loading of mavenrc files 35 | # ---------------------------------------------------------------------------- 36 | 37 | if [ -z "$MAVEN_SKIP_RC" ] ; then 38 | 39 | if [ -f /etc/mavenrc ] ; then 40 | . /etc/mavenrc 41 | fi 42 | 43 | if [ -f "$HOME/.mavenrc" ] ; then 44 | . "$HOME/.mavenrc" 45 | fi 46 | 47 | fi 48 | 49 | # OS specific support. $var _must_ be set to either true or false. 50 | cygwin=false; 51 | darwin=false; 52 | mingw=false 53 | case "`uname`" in 54 | CYGWIN*) cygwin=true ;; 55 | MINGW*) mingw=true;; 56 | Darwin*) darwin=true 57 | # 58 | # Look for the Apple JDKs first to preserve the existing behaviour, and then look 59 | # for the new JDKs provided by Oracle. 60 | # 61 | if [ -z "$JAVA_HOME" ] && [ -L /System/Library/Frameworks/JavaVM.framework/Versions/CurrentJDK ] ; then 62 | # 63 | # Apple JDKs 64 | # 65 | export JAVA_HOME=/System/Library/Frameworks/JavaVM.framework/Versions/CurrentJDK/Home 66 | fi 67 | 68 | if [ -z "$JAVA_HOME" ] && [ -L /System/Library/Java/JavaVirtualMachines/CurrentJDK ] ; then 69 | # 70 | # Apple JDKs 71 | # 72 | export JAVA_HOME=/System/Library/Java/JavaVirtualMachines/CurrentJDK/Contents/Home 73 | fi 74 | 75 | if [ -z "$JAVA_HOME" ] && [ -L "/Library/Java/JavaVirtualMachines/CurrentJDK" ] ; then 76 | # 77 | # Oracle JDKs 78 | # 79 | export JAVA_HOME=/Library/Java/JavaVirtualMachines/CurrentJDK/Contents/Home 80 | fi 81 | 82 | if [ -z "$JAVA_HOME" ] && [ -x "/usr/libexec/java_home" ]; then 83 | # 84 | # Apple JDKs 85 | # 86 | export JAVA_HOME=`/usr/libexec/java_home` 87 | fi 88 | ;; 89 | esac 90 | 91 | if [ -z "$JAVA_HOME" ] ; then 92 | if [ -r /etc/gentoo-release ] ; then 93 | JAVA_HOME=`java-config --jre-home` 94 | fi 95 | fi 96 | 97 | if [ -z "$M2_HOME" ] ; then 98 | ## resolve links - $0 may be a link to maven's home 99 | PRG="$0" 100 | 101 | # need this for relative symlinks 102 | while [ -h "$PRG" ] ; do 103 | ls=`ls -ld "$PRG"` 104 | link=`expr "$ls" : '.*-> \(.*\)$'` 105 | if expr "$link" : '/.*' > /dev/null; then 106 | PRG="$link" 107 | else 108 | PRG="`dirname "$PRG"`/$link" 109 | fi 110 | done 111 | 112 | saveddir=`pwd` 113 | 114 | M2_HOME=`dirname "$PRG"`/.. 115 | 116 | # make it fully qualified 117 | M2_HOME=`cd "$M2_HOME" && pwd` 118 | 119 | cd "$saveddir" 120 | # echo Using m2 at $M2_HOME 121 | fi 122 | 123 | # For Cygwin, ensure paths are in UNIX format before anything is touched 124 | if $cygwin ; then 125 | [ -n "$M2_HOME" ] && 126 | M2_HOME=`cygpath --unix "$M2_HOME"` 127 | [ -n "$JAVA_HOME" ] && 128 | JAVA_HOME=`cygpath --unix "$JAVA_HOME"` 129 | [ -n "$CLASSPATH" ] && 130 | CLASSPATH=`cygpath --path --unix "$CLASSPATH"` 131 | fi 132 | 133 | # For Migwn, ensure paths are in UNIX format before anything is touched 134 | if $mingw ; then 135 | [ -n "$M2_HOME" ] && 136 | M2_HOME="`(cd "$M2_HOME"; pwd)`" 137 | [ -n "$JAVA_HOME" ] && 138 | JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`" 139 | # TODO classpath? 140 | fi 141 | 142 | if [ -z "$JAVA_HOME" ]; then 143 | javaExecutable="`which javac`" 144 | if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then 145 | # readlink(1) is not available as standard on Solaris 10. 146 | readLink=`which readlink` 147 | if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then 148 | if $darwin ; then 149 | javaHome="`dirname \"$javaExecutable\"`" 150 | javaExecutable="`cd \"$javaHome\" && pwd -P`/javac" 151 | else 152 | javaExecutable="`readlink -f \"$javaExecutable\"`" 153 | fi 154 | javaHome="`dirname \"$javaExecutable\"`" 155 | javaHome=`expr "$javaHome" : '\(.*\)/bin'` 156 | JAVA_HOME="$javaHome" 157 | export JAVA_HOME 158 | fi 159 | fi 160 | fi 161 | 162 | if [ -z "$JAVACMD" ] ; then 163 | if [ -n "$JAVA_HOME" ] ; then 164 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 165 | # IBM's JDK on AIX uses strange locations for the executables 166 | JAVACMD="$JAVA_HOME/jre/sh/java" 167 | else 168 | JAVACMD="$JAVA_HOME/bin/java" 169 | fi 170 | else 171 | JAVACMD="`which java`" 172 | fi 173 | fi 174 | 175 | if [ ! -x "$JAVACMD" ] ; then 176 | echo "Error: JAVA_HOME is not defined correctly." >&2 177 | echo " We cannot execute $JAVACMD" >&2 178 | exit 1 179 | fi 180 | 181 | if [ -z "$JAVA_HOME" ] ; then 182 | echo "Warning: JAVA_HOME environment variable is not set." 183 | fi 184 | 185 | CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher 186 | 187 | # For Cygwin, switch paths to Windows format before running java 188 | if $cygwin; then 189 | [ -n "$M2_HOME" ] && 190 | M2_HOME=`cygpath --path --windows "$M2_HOME"` 191 | [ -n "$JAVA_HOME" ] && 192 | JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"` 193 | [ -n "$CLASSPATH" ] && 194 | CLASSPATH=`cygpath --path --windows "$CLASSPATH"` 195 | fi 196 | 197 | # traverses directory structure from process work directory to filesystem root 198 | # first directory with .mvn subdirectory is considered project base directory 199 | find_maven_basedir() { 200 | local basedir=$(pwd) 201 | local wdir=$(pwd) 202 | while [ "$wdir" != '/' ] ; do 203 | if [ -d "$wdir"/.mvn ] ; then 204 | basedir=$wdir 205 | break 206 | fi 207 | wdir=$(cd "$wdir/.."; pwd) 208 | done 209 | echo "${basedir}" 210 | } 211 | 212 | # concatenates all lines of a file 213 | concat_lines() { 214 | if [ -f "$1" ]; then 215 | echo "$(tr -s '\n' ' ' < "$1")" 216 | fi 217 | } 218 | 219 | export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-$(find_maven_basedir)} 220 | MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" 221 | 222 | # Provide a "standardized" way to retrieve the CLI args that will 223 | # work with both Windows and non-Windows executions. 224 | MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@" 225 | export MAVEN_CMD_LINE_ARGS 226 | 227 | WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain 228 | 229 | echo "Running version check" 230 | VERSION=$( sed '\!//' -e 's!.*$!!' ) 231 | echo "The found version is [${VERSION}]" 232 | 233 | if echo $VERSION | egrep -q 'M|RC'; then 234 | echo Activating \"milestone\" profile for version=\"$VERSION\" 235 | echo $MAVEN_ARGS | grep -q milestone || MAVEN_ARGS="$MAVEN_ARGS -Pmilestone" 236 | else 237 | echo Deactivating \"milestone\" profile for version=\"$VERSION\" 238 | echo $MAVEN_ARGS | grep -q milestone && MAVEN_ARGS=$(echo $MAVEN_ARGS | sed -e 's/-Pmilestone//') 239 | fi 240 | 241 | if echo $VERSION | egrep -q '[0-9]*\.[0-9]*\.[0-9]*$|RELEASE'; then 242 | echo Activating \"central\" profile for version=\"$VERSION\" 243 | echo $MAVEN_ARGS | grep -q milestone || MAVEN_ARGS="$MAVEN_ARGS -Pcentral" 244 | else 245 | echo Deactivating \"central\" profile for version=\"$VERSION\" 246 | echo $MAVEN_ARGS | grep -q central && MAVEN_ARGS=$(echo $MAVEN_ARGS | sed -e 's/-Pcentral//') 247 | fi 248 | 249 | exec "$JAVACMD" \ 250 | $MAVEN_OPTS \ 251 | -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ 252 | "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ 253 | ${WRAPPER_LAUNCHER} ${MAVEN_ARGS} "$@" 254 | -------------------------------------------------------------------------------- /mvnw.cmd: -------------------------------------------------------------------------------- 1 | @REM ---------------------------------------------------------------------------- 2 | @REM Licensed to the Apache Software Foundation (ASF) under one 3 | @REM or more contributor license agreements. See the NOTICE file 4 | @REM distributed with this work for additional information 5 | @REM regarding copyright ownership. The ASF licenses this file 6 | @REM to you under the Apache License, Version 2.0 (the 7 | @REM "License"); you may not use this file except in compliance 8 | @REM with the License. You may obtain a copy of the License at 9 | @REM 10 | @REM https://www.apache.org/licenses/LICENSE-2.0 11 | @REM 12 | @REM Unless required by applicable law or agreed to in writing, 13 | @REM software distributed under the License is distributed on an 14 | @REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | @REM KIND, either express or implied. See the License for the 16 | @REM specific language governing permissions and limitations 17 | @REM under the License. 18 | @REM ---------------------------------------------------------------------------- 19 | 20 | @REM ---------------------------------------------------------------------------- 21 | @REM Maven2 Start Up Batch script 22 | @REM 23 | @REM Required ENV vars: 24 | @REM JAVA_HOME - location of a JDK home dir 25 | @REM 26 | @REM Optional ENV vars 27 | @REM M2_HOME - location of maven2's installed home dir 28 | @REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands 29 | @REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a key stroke before ending 30 | @REM MAVEN_OPTS - parameters passed to the Java VM when running Maven 31 | @REM e.g. to debug Maven itself, use 32 | @REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 33 | @REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files 34 | @REM ---------------------------------------------------------------------------- 35 | 36 | @REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' 37 | @echo off 38 | @REM enable echoing my setting MAVEN_BATCH_ECHO to 'on' 39 | @if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% 40 | 41 | @REM set %HOME% to equivalent of $HOME 42 | if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") 43 | 44 | @REM Execute a user defined script before this one 45 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre 46 | @REM check for pre script, once with legacy .bat ending and once with .cmd ending 47 | if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat" 48 | if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd" 49 | :skipRcPre 50 | 51 | @setlocal 52 | 53 | set ERROR_CODE=0 54 | 55 | @REM To isolate internal variables from possible post scripts, we use another setlocal 56 | @setlocal 57 | 58 | @REM ==== START VALIDATION ==== 59 | if not "%JAVA_HOME%" == "" goto OkJHome 60 | 61 | echo. 62 | echo Error: JAVA_HOME not found in your environment. >&2 63 | echo Please set the JAVA_HOME variable in your environment to match the >&2 64 | echo location of your Java installation. >&2 65 | echo. 66 | goto error 67 | 68 | :OkJHome 69 | if exist "%JAVA_HOME%\bin\java.exe" goto init 70 | 71 | echo. 72 | echo Error: JAVA_HOME is set to an invalid directory. >&2 73 | echo JAVA_HOME = "%JAVA_HOME%" >&2 74 | echo Please set the JAVA_HOME variable in your environment to match the >&2 75 | echo location of your Java installation. >&2 76 | echo. 77 | goto error 78 | 79 | @REM ==== END VALIDATION ==== 80 | 81 | :init 82 | 83 | set MAVEN_CMD_LINE_ARGS=%* 84 | 85 | @REM Find the project base dir, i.e. the directory that contains the folder ".mvn". 86 | @REM Fallback to current working directory if not found. 87 | 88 | set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% 89 | IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir 90 | 91 | set EXEC_DIR=%CD% 92 | set WDIR=%EXEC_DIR% 93 | :findBaseDir 94 | IF EXIST "%WDIR%"\.mvn goto baseDirFound 95 | cd .. 96 | IF "%WDIR%"=="%CD%" goto baseDirNotFound 97 | set WDIR=%CD% 98 | goto findBaseDir 99 | 100 | :baseDirFound 101 | set MAVEN_PROJECTBASEDIR=%WDIR% 102 | cd "%EXEC_DIR%" 103 | goto endDetectBaseDir 104 | 105 | :baseDirNotFound 106 | set MAVEN_PROJECTBASEDIR=%EXEC_DIR% 107 | cd "%EXEC_DIR%" 108 | 109 | :endDetectBaseDir 110 | 111 | IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig 112 | 113 | @setlocal EnableExtensions EnableDelayedExpansion 114 | for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a 115 | @endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% 116 | 117 | :endReadAdditionalConfig 118 | 119 | SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" 120 | 121 | set WRAPPER_JAR="".\.mvn\wrapper\maven-wrapper.jar"" 122 | set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain 123 | 124 | %MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CMD_LINE_ARGS% 125 | if ERRORLEVEL 1 goto error 126 | goto end 127 | 128 | :error 129 | set ERROR_CODE=1 130 | 131 | :end 132 | @endlocal & set ERROR_CODE=%ERROR_CODE% 133 | 134 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost 135 | @REM check for post script, once with legacy .bat ending and once with .cmd ending 136 | if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat" 137 | if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd" 138 | :skipRcPost 139 | 140 | @REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' 141 | if "%MAVEN_BATCH_PAUSE%" == "on" pause 142 | 143 | if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE% 144 | 145 | exit /B %ERROR_CODE% 146 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | org.springframework.guice 7 | spring-guice 8 | 3.0.1-SNAPSHOT 9 | 10 | spring-guice 11 | Utilities for using Spring with Guice and vice versa 12 | https://github.com/spring-projects/spring-guice 13 | 14 | 15 | 16 | 17 | org.springframework 18 | spring-framework-bom 19 | ${spring.version} 20 | pom 21 | import 22 | 23 | 24 | 25 | 26 | 27 | 28 | org.springframework 29 | spring-context 30 | 31 | 32 | com.google.inject 33 | guice 34 | 7.0.0 35 | compile 36 | 37 | 38 | com.google.inject.extensions 39 | guice-throwingproviders 40 | 7.0.0 41 | test 42 | 43 | 44 | jakarta.annotation 45 | jakarta.annotation-api 46 | 3.0.0 47 | 48 | 49 | org.springframework 50 | spring-test 51 | test 52 | 53 | 54 | org.junit.jupiter 55 | junit-jupiter-api 56 | 5.8.2 57 | test 58 | 59 | 60 | org.junit.jupiter 61 | junit-jupiter-engine 62 | 5.8.2 63 | test 64 | 65 | 66 | org.junit.platform 67 | junit-platform-suite-engine 68 | 1.8.2 69 | test 70 | 71 | 72 | org.assertj 73 | assertj-core 74 | 3.22.0 75 | test 76 | 77 | 78 | org.mockito 79 | mockito-core 80 | 4.3.1 81 | test 82 | 83 | 84 | 85 | 86 | 17 87 | UTF-8 88 | UTF-8 89 | 6.1.10 90 | 91 | 2024-07-12T09:48:18Z 92 | 93 | 94 | 95 | 96 | 97 | 98 | org.apache.maven.plugins 99 | maven-release-plugin 100 | 2.3 101 | 102 | 103 | 104 | 105 | 106 | org.apache.maven.plugins 107 | maven-compiler-plugin 108 | 3.1 109 | 110 | ${java.version} 111 | ${java.version} 112 | 113 | 114 | 115 | org.apache.maven.plugins 116 | maven-surefire-plugin 117 | 2.22.2 118 | 119 | 120 | 121 | **/*Tests.java 122 | 123 | 124 | **/Abstract*.java 125 | 126 | 127 | 128 | 129 | maven-javadoc-plugin 130 | 3.3.1 131 | 132 | 133 | javadoc 134 | 135 | jar 136 | 137 | package 138 | 139 | 140 | 141 | 142 | maven-source-plugin 143 | 3.2.1 144 | 145 | 146 | attach-sources 147 | 148 | jar 149 | 150 | package 151 | 152 | 153 | 154 | 155 | io.spring.javaformat 156 | spring-javaformat-maven-plugin 157 | 0.0.31 158 | 159 | 160 | 161 | validate 162 | true 163 | 164 | validate 165 | 166 | 167 | 168 | 169 | 170 | org.apache.maven.plugins 171 | maven-checkstyle-plugin 172 | 3.1.1 173 | 174 | 175 | com.puppycrawl.tools 176 | checkstyle 177 | 8.45.1 178 | 179 | 180 | io.spring.javaformat 181 | spring-javaformat-checkstyle 182 | 0.0.31 183 | 184 | 185 | 186 | 187 | checkstyle-validation 188 | validate 189 | true 190 | 191 | config/checkstyle/checkstyle.xml 192 | true 193 | 194 | 195 | check 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | Pivotal Software, Inc. 205 | https://www.spring.io 206 | 207 | 208 | 209 | https://github.com/spring-projects/spring-guice 210 | scm:git:git://github.com/spring-projects/spring-guice.git 211 | scm:git:ssh://git@github.com/spring-projects/spring-guice.git 212 | HEAD 213 | 214 | 215 | 216 | 217 | dsyer 218 | Dave Syer 219 | dsyer@gopivotal.com 220 | 221 | 222 | 223 | 224 | 225 | Apache License, Version 2.0 226 | https://www.apache.org/licenses/LICENSE-2.0 227 | 228 | Copyright 2014-2015 the original author or authors. 229 | 230 | Licensed under the Apache License, Version 2.0 (the "License"); 231 | you may not use this file except in compliance with the License. 232 | You may obtain a copy of the License at 233 | 234 | https://www.apache.org/licenses/LICENSE-2.0 235 | 236 | Unless required by applicable law or agreed to in writing, software 237 | distributed under the License is distributed on an "AS IS" BASIS, 238 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 239 | implied. 240 | 241 | See the License for the specific language governing permissions and 242 | limitations under the License. 243 | 244 | 245 | 246 | 247 | 248 | https://github.com/spring-projects/spring-guice 249 | 250 | spring-docs 251 | scp://static.springframework.org/var/www/domains/springframework.org/static/htdocs/spring-guice/docs/${project.artifactId}/${project.version} 252 | 253 | 254 | sonatype-nexus-staging 255 | Nexus Release Repository 256 | https://s01.oss.sonatype.org/service/local/staging/deploy/maven2/ 257 | 258 | 259 | repo.spring.io 260 | Spring Snapshot Repository 261 | https://repo.spring.io/libs-snapshot-local 262 | 263 | 264 | 265 | 266 | 267 | milestone 268 | 269 | 270 | repo.spring.io 271 | Spring Milestone Repository 272 | https://repo.spring.io/libs-milestone-local 273 | 274 | 275 | 276 | 277 | central 278 | 279 | 280 | 281 | org.apache.maven.plugins 282 | maven-gpg-plugin 283 | 1.6 284 | 285 | 286 | sign-artifacts 287 | verify 288 | 289 | sign 290 | 291 | 292 | 293 | 294 | 295 | --batch 296 | --pinentry-mode=loopback 297 | 298 | 299 | 300 | 301 | 302 | 303 | 304 | 305 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/guice/annotation/EnableGuiceModules.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2013-2014 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.guice.annotation; 18 | 19 | import java.lang.annotation.Documented; 20 | import java.lang.annotation.ElementType; 21 | import java.lang.annotation.Retention; 22 | import java.lang.annotation.RetentionPolicy; 23 | import java.lang.annotation.Target; 24 | 25 | import com.google.inject.Module; 26 | 27 | import org.springframework.context.annotation.Import; 28 | 29 | /** 30 | * Enable spring beans that are themselves a Guice {@link Module} to contribute 31 | * dependencies via the bindings in Guice. 32 | * 33 | * @author Dave Syer 34 | * 35 | */ 36 | @Target(ElementType.TYPE) 37 | @Retention(RetentionPolicy.RUNTIME) 38 | @Documented 39 | @Import(ModuleRegistryConfiguration.class) 40 | public @interface EnableGuiceModules { 41 | 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/guice/annotation/GuiceFactoryBean.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2013-2014 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.guice.annotation; 18 | 19 | import com.google.inject.Injector; 20 | import com.google.inject.Key; 21 | import jakarta.inject.Provider; 22 | 23 | import org.springframework.beans.factory.FactoryBean; 24 | 25 | /** 26 | * Convenience class used to map a Guice {@link Provider} to a Spring bean. 27 | * 28 | * @param the bean type 29 | * @author Dave Syer 30 | */ 31 | class GuiceFactoryBean implements FactoryBean { 32 | 33 | private final Key key; 34 | 35 | private final Class beanType; 36 | 37 | private final boolean isSingleton; 38 | 39 | private final Provider injector; 40 | 41 | GuiceFactoryBean(Class beanType, Key key, boolean isSingleton, Provider injector) { 42 | this.beanType = beanType; 43 | this.key = key; 44 | this.isSingleton = isSingleton; 45 | this.injector = injector; 46 | } 47 | 48 | @Override 49 | public T getObject() throws Exception { 50 | return (T) this.injector.get().getInstance(this.key); 51 | } 52 | 53 | @Override 54 | public Class getObjectType() { 55 | return this.beanType; 56 | } 57 | 58 | @Override 59 | public boolean isSingleton() { 60 | return this.isSingleton; 61 | } 62 | 63 | } 64 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/guice/annotation/GuiceModule.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2013-2014 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.guice.annotation; 18 | 19 | import java.lang.annotation.Documented; 20 | import java.lang.annotation.ElementType; 21 | import java.lang.annotation.Retention; 22 | import java.lang.annotation.RetentionPolicy; 23 | import java.lang.annotation.Target; 24 | 25 | import org.springframework.context.annotation.ComponentScan.Filter; 26 | import org.springframework.context.annotation.Import; 27 | import org.springframework.guice.module.GuiceModuleMetadata; 28 | import org.springframework.guice.module.SpringModule; 29 | 30 | /** 31 | * Annotation that decorates the whole application context and provides metadata to Guice 32 | * if the context is used as a Module. Can be added to any @Configuration 33 | * class (and if added to many then the filters are combined with logical OR). By default 34 | * all beans in the context will be bound to Guice with all of their implemented 35 | * interfaces. If you need to filter out which beans are added you can filter by class. 36 | * 37 | * @author Dave Syer 38 | * 39 | * @see SpringModule 40 | * @see GuiceModuleMetadata 41 | * 42 | */ 43 | @Target(ElementType.TYPE) 44 | @Retention(RetentionPolicy.RUNTIME) 45 | @Documented 46 | @Import(GuiceModuleRegistrar.class) 47 | public @interface GuiceModule { 48 | 49 | /** 50 | * Specifies which types are eligible for inclusion in Guice module. 51 | * @return filters for inclusion 52 | */ 53 | Filter[] includeFilters() default {}; 54 | 55 | /** 56 | * Specifies which types are not eligible for inclusion in Guice module. 57 | * @return filters for exclusion 58 | */ 59 | Filter[] excludeFilters() default {}; 60 | 61 | /** 62 | * Specifies which names (by regex) are eligible for inclusion in Guice module. 63 | * @return regexes 64 | */ 65 | String[] includePatterns() default {}; 66 | 67 | /** 68 | * Specifies which bean names (by regex) are not eligible for inclusion in Guice 69 | * module. 70 | * @return regexes 71 | */ 72 | String[] excludePatterns() default {}; 73 | 74 | /** 75 | * Specifies which names (by simple wildcard match) are eligible for inclusion in 76 | * Guice module. 77 | * @return bean names 78 | */ 79 | String[] includeNames() default {}; 80 | 81 | /** 82 | * Specifies which bean names (by simple wildcard match) are not eligible for 83 | * inclusion in Guice module. 84 | * @return bean names 85 | */ 86 | String[] excludeNames() default {}; 87 | 88 | } 89 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/guice/annotation/GuiceModuleRegistrar.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012-2013 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.guice.annotation; 18 | 19 | import java.lang.annotation.Annotation; 20 | import java.util.ArrayList; 21 | import java.util.Collection; 22 | import java.util.HashSet; 23 | import java.util.List; 24 | import java.util.Set; 25 | import java.util.regex.Pattern; 26 | 27 | import org.springframework.beans.BeanUtils; 28 | import org.springframework.beans.factory.FactoryBean; 29 | import org.springframework.beans.factory.support.AbstractBeanDefinition; 30 | import org.springframework.beans.factory.support.BeanDefinitionBuilder; 31 | import org.springframework.beans.factory.support.BeanDefinitionRegistry; 32 | import org.springframework.beans.factory.support.DefaultBeanNameGenerator; 33 | import org.springframework.context.ResourceLoaderAware; 34 | import org.springframework.context.annotation.FilterType; 35 | import org.springframework.context.annotation.ImportBeanDefinitionRegistrar; 36 | import org.springframework.core.annotation.AnnotationAttributes; 37 | import org.springframework.core.io.DefaultResourceLoader; 38 | import org.springframework.core.io.ResourceLoader; 39 | import org.springframework.core.type.AnnotationMetadata; 40 | import org.springframework.core.type.filter.AnnotationTypeFilter; 41 | import org.springframework.core.type.filter.AspectJTypeFilter; 42 | import org.springframework.core.type.filter.AssignableTypeFilter; 43 | import org.springframework.core.type.filter.RegexPatternTypeFilter; 44 | import org.springframework.core.type.filter.TypeFilter; 45 | import org.springframework.guice.module.GuiceModuleMetadata; 46 | import org.springframework.util.Assert; 47 | 48 | /** 49 | * Registers bean definitions for Guice modules. 50 | * 51 | * @author Dave Syer 52 | * 53 | */ 54 | class GuiceModuleRegistrar implements ImportBeanDefinitionRegistrar, ResourceLoaderAware { 55 | 56 | private ResourceLoader resourceLoader = new DefaultResourceLoader(); 57 | 58 | @Override 59 | public void setResourceLoader(ResourceLoader resourceLoader) { 60 | this.resourceLoader = resourceLoader; 61 | } 62 | 63 | @Override 64 | public void registerBeanDefinitions(AnnotationMetadata annotation, BeanDefinitionRegistry registry) { 65 | BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(GuiceModuleMetadataFactory.class); 66 | builder.addPropertyValue("includeFilters", parseFilters(annotation, "includeFilters")); 67 | builder.addPropertyValue("excludeFilters", parseFilters(annotation, "excludeFilters")); 68 | builder.addPropertyValue("includePatterns", parsePatterns(annotation, "includePatterns")); 69 | builder.addPropertyValue("excludePatterns", parsePatterns(annotation, "excludePatterns")); 70 | builder.addPropertyValue("includeNames", parseNames(annotation, "includeNames")); 71 | builder.addPropertyValue("excludeNames", parseNames(annotation, "excludeNames")); 72 | AbstractBeanDefinition definition = builder.getBeanDefinition(); 73 | String name = new DefaultBeanNameGenerator().generateBeanName(definition, registry); 74 | registry.registerBeanDefinition(name, definition); 75 | } 76 | 77 | private Set parsePatterns(AnnotationMetadata annotation, String attributeName) { 78 | Set result = new HashSet(); 79 | AnnotationAttributes attributes = new AnnotationAttributes( 80 | annotation.getAnnotationAttributes(GuiceModule.class.getName())); 81 | String[] filters = attributes.getStringArray(attributeName); 82 | 83 | for (String filter : filters) { 84 | result.add(Pattern.compile(filter)); 85 | } 86 | 87 | return result; 88 | } 89 | 90 | private Set parseNames(AnnotationMetadata annotation, String attributeName) { 91 | Set result = new HashSet(); 92 | AnnotationAttributes attributes = new AnnotationAttributes( 93 | annotation.getAnnotationAttributes(GuiceModule.class.getName())); 94 | String[] filters = attributes.getStringArray(attributeName); 95 | 96 | for (String filter : filters) { 97 | result.add(filter); 98 | } 99 | 100 | return result; 101 | } 102 | 103 | private Set parseFilters(AnnotationMetadata annotation, String attributeName) { 104 | 105 | Set result = new HashSet(); 106 | AnnotationAttributes attributes = new AnnotationAttributes( 107 | annotation.getAnnotationAttributes(GuiceModule.class.getName())); 108 | AnnotationAttributes[] filters = attributes.getAnnotationArray(attributeName); 109 | 110 | for (AnnotationAttributes filter : filters) { 111 | result.addAll(typeFiltersFor(filter)); 112 | } 113 | 114 | return result; 115 | } 116 | 117 | private List typeFiltersFor(AnnotationAttributes filterAttributes) { 118 | 119 | List typeFilters = new ArrayList(); 120 | FilterType filterType = filterAttributes.getEnum("type"); 121 | 122 | for (Class filterClass : filterAttributes.getClassArray("value")) { 123 | switch (filterType) { 124 | case ANNOTATION: 125 | Assert.isAssignable(Annotation.class, filterClass, 126 | "An error occured when processing a @ComponentScan " + "ANNOTATION type filter: "); 127 | @SuppressWarnings("unchecked") 128 | Class annoClass = (Class) filterClass; 129 | typeFilters.add(new AnnotationTypeFilter(annoClass)); 130 | break; 131 | case ASSIGNABLE_TYPE: 132 | typeFilters.add(new AssignableTypeFilter(filterClass)); 133 | break; 134 | case CUSTOM: 135 | Assert.isAssignable(TypeFilter.class, filterClass, 136 | "An error occured when processing a @ComponentScan " + "CUSTOM type filter: "); 137 | typeFilters.add(BeanUtils.instantiateClass(filterClass, TypeFilter.class)); 138 | break; 139 | default: 140 | throw new IllegalArgumentException("Unknown filter type " + filterType); 141 | } 142 | } 143 | 144 | for (String expression : getPatterns(filterAttributes)) { 145 | 146 | String rawName = filterType.toString(); 147 | 148 | if ("REGEX".equals(rawName)) { 149 | typeFilters.add(new RegexPatternTypeFilter(Pattern.compile(expression))); 150 | } 151 | else if ("ASPECTJ".equals(rawName)) { 152 | typeFilters.add(new AspectJTypeFilter(expression, this.resourceLoader.getClassLoader())); 153 | } 154 | else { 155 | throw new IllegalArgumentException("Unknown filter type " + filterType); 156 | } 157 | } 158 | 159 | return typeFilters; 160 | } 161 | 162 | private String[] getPatterns(AnnotationAttributes filterAttributes) { 163 | 164 | try { 165 | return filterAttributes.getStringArray("pattern"); 166 | } 167 | catch (IllegalArgumentException ex) { 168 | return new String[0]; 169 | } 170 | } 171 | 172 | protected static class GuiceModuleMetadataFactory implements FactoryBean { 173 | 174 | private Collection includeFilters; 175 | 176 | private Collection excludeFilters; 177 | 178 | private Collection includePatterns; 179 | 180 | private Collection excludePatterns; 181 | 182 | private Collection includeNames; 183 | 184 | private Collection excludeNames; 185 | 186 | public void setIncludeFilters(Collection includeFilters) { 187 | this.includeFilters = includeFilters; 188 | } 189 | 190 | public void setExcludeFilters(Collection excludeFilters) { 191 | this.excludeFilters = excludeFilters; 192 | } 193 | 194 | public void setIncludePatterns(Collection includePatterns) { 195 | this.includePatterns = includePatterns; 196 | } 197 | 198 | public void setExcludePatterns(Collection excludePatterns) { 199 | this.excludePatterns = excludePatterns; 200 | } 201 | 202 | public void setIncludeNames(Collection includeNames) { 203 | this.includeNames = includeNames; 204 | } 205 | 206 | public void setExcludeNames(Collection excludeNames) { 207 | this.excludeNames = excludeNames; 208 | } 209 | 210 | @Override 211 | public GuiceModuleMetadata getObject() throws Exception { 212 | return new GuiceModuleMetadata() 213 | .include(this.includeFilters.toArray(new TypeFilter[this.includeFilters.size()])) 214 | .exclude(this.excludeFilters.toArray(new TypeFilter[this.excludeFilters.size()])) 215 | .include(this.includePatterns.toArray(new Pattern[this.includePatterns.size()])) 216 | .exclude(this.excludePatterns.toArray(new Pattern[this.excludePatterns.size()])) 217 | .include(this.includeNames.toArray(new String[this.includeNames.size()])) 218 | .exclude(this.excludeNames.toArray(new String[this.excludeNames.size()])); 219 | } 220 | 221 | @Override 222 | public Class getObjectType() { 223 | return GuiceModuleMetadata.class; 224 | } 225 | 226 | @Override 227 | public boolean isSingleton() { 228 | return false; 229 | } 230 | 231 | } 232 | 233 | } 234 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/guice/annotation/InjectorFactory.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2022 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.guice.annotation; 18 | 19 | import java.util.List; 20 | 21 | import com.google.inject.Injector; 22 | import com.google.inject.Module; 23 | 24 | /*** 25 | * Factory which allows for custom creation of the Guice Injector to be used in 26 | * the @{@link EnableGuiceModules} feature. 27 | * 28 | * @author Dave Syer 29 | * @author Taylor Wicksell 30 | */ 31 | public interface InjectorFactory { 32 | 33 | Injector createInjector(List modules); 34 | 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/guice/annotation/ModuleFilter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2013-2014 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.guice.annotation; 18 | 19 | import java.util.function.Predicate; 20 | 21 | import com.google.inject.Module; 22 | 23 | import org.springframework.beans.factory.support.BeanDefinitionRegistry; 24 | 25 | /** 26 | * A filter to remove {@link Module}:s from the context before any initialization code is 27 | * run. If one implementation of this interface returns false from its 28 | * {@link #test(Object)} method, the {@link Module} is removed. See 29 | * {@link ModuleRegistryConfiguration#postProcessBeanDefinitionRegistry(BeanDefinitionRegistry)} 30 | * 31 | * @author Niklas Herder 32 | * 33 | */ 34 | 35 | public interface ModuleFilter extends Predicate { 36 | 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/guice/injector/SpringInjector.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2013-2014 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.guice.injector; 18 | 19 | import java.lang.annotation.Annotation; 20 | import java.util.List; 21 | import java.util.Map; 22 | import java.util.Set; 23 | 24 | import com.google.inject.Binding; 25 | import com.google.inject.Injector; 26 | import com.google.inject.Key; 27 | import com.google.inject.MembersInjector; 28 | import com.google.inject.Module; 29 | import com.google.inject.Provider; 30 | import com.google.inject.Scope; 31 | import com.google.inject.TypeLiteral; 32 | import com.google.inject.name.Named; 33 | import com.google.inject.spi.Element; 34 | import com.google.inject.spi.InjectionPoint; 35 | import com.google.inject.spi.TypeConverterBinding; 36 | import jakarta.inject.Qualifier; 37 | 38 | import org.springframework.beans.factory.annotation.BeanFactoryAnnotationUtils; 39 | import org.springframework.beans.factory.annotation.QualifierAnnotationAutowireCandidateResolver; 40 | import org.springframework.beans.factory.support.AutowireCandidateResolver; 41 | import org.springframework.beans.factory.support.DefaultListableBeanFactory; 42 | import org.springframework.beans.factory.support.RootBeanDefinition; 43 | import org.springframework.context.ApplicationContext; 44 | import org.springframework.core.SpringVersion; 45 | 46 | /** 47 | * An {@link Injector} that wraps an {@link ApplicationContext}, and can be used to expose 48 | * the Guice APIs over a Spring application. Does not use Guice at all internally: just 49 | * adapts the Spring API to the Guice one. 50 | * 51 | * @author Dave Syer 52 | * 53 | */ 54 | public class SpringInjector implements Injector { 55 | 56 | private Injector injector; 57 | 58 | private DefaultListableBeanFactory beanFactory; 59 | 60 | private static boolean JAKARTA = false; 61 | 62 | public SpringInjector(ApplicationContext context) { 63 | this.beanFactory = (DefaultListableBeanFactory) context.getAutowireCapableBeanFactory(); 64 | AutowireCandidateResolver resolver = this.beanFactory.getAutowireCandidateResolver(); 65 | if (resolver instanceof QualifierAnnotationAutowireCandidateResolver && JAKARTA) { 66 | // Guice does not yet support jakarta namespace but we can help Spring 6 to 67 | // recognize jakarta.inject 68 | QualifierAnnotationAutowireCandidateResolver qualified = (QualifierAnnotationAutowireCandidateResolver) resolver; 69 | qualified.addQualifierType(Qualifier.class); 70 | } 71 | if (context.getBeanNamesForType(Injector.class, true, false).length > 0) { 72 | this.injector = context.getBean(Injector.class); 73 | } 74 | } 75 | 76 | @Override 77 | public void injectMembers(Object instance) { 78 | this.beanFactory.autowireBean(instance); 79 | } 80 | 81 | @Override 82 | public MembersInjector getMembersInjector(TypeLiteral typeLiteral) { 83 | return new MembersInjector() { 84 | @Override 85 | public void injectMembers(T instance) { 86 | SpringInjector.this.beanFactory.autowireBean(instance); 87 | } 88 | }; 89 | } 90 | 91 | @Override 92 | public MembersInjector getMembersInjector(Class type) { 93 | return getMembersInjector(TypeLiteral.get(type)); 94 | } 95 | 96 | @Override 97 | public Map, Binding> getBindings() { 98 | return null; 99 | } 100 | 101 | @Override 102 | public Map, Binding> getAllBindings() { 103 | return null; 104 | } 105 | 106 | @Override 107 | public Binding getBinding(Key key) { 108 | return null; 109 | } 110 | 111 | @Override 112 | public Binding getBinding(Class type) { 113 | return null; 114 | } 115 | 116 | @Override 117 | public Binding getExistingBinding(Key key) { 118 | return null; 119 | } 120 | 121 | @Override 122 | public List> findBindingsByType(TypeLiteral type) { 123 | return null; 124 | } 125 | 126 | @Override 127 | public Provider getProvider(Key key) { 128 | // TODO: support for other metadata in the key (apart from name and 129 | // type) 130 | Class type = key.getTypeLiteral().getRawType(); 131 | final String name = extractName(key); 132 | if (this.beanFactory.getBeanNamesForType(type, true, false).length == 0) { 133 | if (this.injector != null) { 134 | return this.injector.getProvider(key); 135 | } 136 | // TODO: use prototype scope? 137 | this.beanFactory.registerBeanDefinition(name, new RootBeanDefinition(type)); 138 | } 139 | if (this.beanFactory.containsBean(name) && this.beanFactory.isTypeMatch(name, type)) { 140 | return new Provider() { 141 | @SuppressWarnings("unchecked") 142 | @Override 143 | public T get() { 144 | return (T) SpringInjector.this.beanFactory.getBean(name); 145 | } 146 | }; 147 | } 148 | @SuppressWarnings("unchecked") 149 | final Class cls = (Class) type; 150 | return new Provider() { 151 | @SuppressWarnings("unchecked") 152 | @Override 153 | public T get() { 154 | if (key.getAnnotation() != null) { 155 | return (T) BeanFactoryAnnotationUtils.qualifiedBeanOfType(SpringInjector.this.beanFactory, type, 156 | name); 157 | } 158 | return SpringInjector.this.beanFactory.getBean(cls); 159 | } 160 | }; 161 | } 162 | 163 | private String extractName(Key key) { 164 | final Annotation annotation = key.getAnnotation(); 165 | if (annotation instanceof Named) { 166 | return ((Named) annotation).value(); 167 | } 168 | else if (annotation instanceof jakarta.inject.Named) { 169 | return ((jakarta.inject.Named) annotation).value(); 170 | } 171 | return key.getTypeLiteral().getRawType().getSimpleName(); 172 | } 173 | 174 | @Override 175 | public Provider getProvider(Class type) { 176 | return getProvider(Key.get(type)); 177 | } 178 | 179 | @Override 180 | public T getInstance(Key key) { 181 | return getProvider(key).get(); 182 | } 183 | 184 | @Override 185 | public T getInstance(Class type) { 186 | return getInstance(Key.get(type)); 187 | } 188 | 189 | @Override 190 | public Injector getParent() { 191 | return null; 192 | } 193 | 194 | @Override 195 | public Injector createChildInjector(Iterable modules) { 196 | return null; 197 | } 198 | 199 | @Override 200 | public Injector createChildInjector(Module... modules) { 201 | return null; 202 | } 203 | 204 | @Override 205 | public Map, Scope> getScopeBindings() { 206 | return null; 207 | } 208 | 209 | @Override 210 | public Set getTypeConverterBindings() { 211 | return null; 212 | } 213 | 214 | @Override 215 | public List getElements() { 216 | return null; 217 | } 218 | 219 | @Override 220 | public Map, List> getAllMembersInjectorInjectionPoints() { 221 | return null; 222 | } 223 | 224 | static { 225 | String version = SpringVersion.getVersion(); 226 | if (version != null && version.contains(".")) { 227 | version = version.substring(0, version.indexOf(".")); 228 | if (Integer.parseInt(version) > 5) { 229 | JAKARTA = true; 230 | } 231 | } 232 | } 233 | 234 | } 235 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/guice/module/BeanFactoryProvider.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2017 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.guice.module; 18 | 19 | import java.io.Closeable; 20 | import java.io.IOException; 21 | import java.util.ArrayList; 22 | import java.util.Arrays; 23 | import java.util.List; 24 | import java.util.concurrent.atomic.AtomicBoolean; 25 | 26 | import com.google.inject.spi.ProvisionListener; 27 | import jakarta.inject.Provider; 28 | 29 | import org.springframework.beans.BeansException; 30 | import org.springframework.beans.factory.BeanFactory; 31 | import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; 32 | import org.springframework.context.ApplicationContext; 33 | import org.springframework.context.ApplicationContextInitializer; 34 | import org.springframework.context.ConfigurableApplicationContext; 35 | import org.springframework.context.annotation.AnnotationConfigApplicationContext; 36 | import org.springframework.core.OrderComparator; 37 | 38 | /** 39 | *

40 | * A {@link Provider} for a {@link BeanFactory} from an {@link ApplicationContext} that 41 | * will not be refreshed until the Guice injector wants to resolve dependencies. Delaying 42 | * the refresh means that the bean factory can resolve dependencies from Guice modules 43 | * (and vice versa). 44 | *

45 | *

46 | * Also implements {@link Closeable} so if you want to clean up resources used in the 47 | * application context then you can keep a reference to the provider and call 48 | * {@link #close()} on it when the application is shut down. Alternatively, you could 49 | * register an {@link ApplicationContextInitializer} that sets a shutdown hook, so that 50 | * the context is closed automatically when the JVM ends. 51 | *

52 | * 53 | * @author Dave Syer 54 | * 55 | */ 56 | @SuppressWarnings("checkstyle:FinalClass") 57 | public class BeanFactoryProvider implements Provider, Closeable { 58 | 59 | private Class[] config; 60 | 61 | private String[] basePackages; 62 | 63 | private List> initializers = new ArrayList>(); 64 | 65 | private PartiallyRefreshableApplicationContext context; 66 | 67 | /** 68 | * Create an application context by scanning these base packages. 69 | * @param basePackages base packages to scan 70 | * @return a provider 71 | */ 72 | public static BeanFactoryProvider from(String... basePackages) { 73 | return new BeanFactoryProvider(null, basePackages); 74 | } 75 | 76 | /** 77 | * Create an application context using these configuration classes. 78 | * @param config classes to build an application 79 | * @return a provider 80 | */ 81 | public static BeanFactoryProvider from(Class... config) { 82 | return new BeanFactoryProvider(config, null); 83 | } 84 | 85 | @SuppressWarnings("unchecked") 86 | public BeanFactoryProvider initializer( 87 | ApplicationContextInitializer... initializers) { 88 | this.initializers.addAll(Arrays.asList(initializers)); 89 | return this; 90 | } 91 | 92 | private BeanFactoryProvider(Class[] config, String[] basePackages) { 93 | this.config = config; 94 | this.basePackages = basePackages; 95 | } 96 | 97 | @Override 98 | public void close() throws IOException { 99 | if (this.context != null) { 100 | synchronized (this) { 101 | if (this.context != null) { 102 | this.context.close(); 103 | this.context = null; 104 | } 105 | } 106 | } 107 | } 108 | 109 | @Override 110 | public ConfigurableListableBeanFactory get() { 111 | if (this.context == null) { 112 | synchronized (this) { 113 | if (this.context == null) { 114 | PartiallyRefreshableApplicationContext context = new PartiallyRefreshableApplicationContext(); 115 | if (this.config != null && this.config.length > 0) { 116 | context.register(this.config); 117 | } 118 | if (this.basePackages != null && this.basePackages.length > 0) { 119 | context.scan(this.basePackages); 120 | } 121 | context.partialRefresh(); 122 | if (this.initializers != null && !this.initializers.isEmpty()) { 123 | OrderComparator.sort(this.initializers); 124 | for (ApplicationContextInitializer initializer : this.initializers) { 125 | initializer.initialize(context); 126 | } 127 | } 128 | this.context = context; 129 | } 130 | } 131 | } 132 | return this.context.getBeanFactory(); 133 | } 134 | 135 | private static final class PartiallyRefreshableApplicationContext extends AnnotationConfigApplicationContext { 136 | 137 | private final AtomicBoolean partiallyRefreshed = new AtomicBoolean(false); 138 | 139 | /* 140 | * Initializes beanFactoryPostProcessors only to ensure that all BeanDefinition's 141 | * are available 142 | */ 143 | private void partialRefresh() { 144 | ConfigurableListableBeanFactory beanFactory = getBeanFactory(); 145 | beanFactory.registerSingleton("refreshListener", new ContextRefreshingProvisionListener(this)); 146 | prepareBeanFactory(beanFactory); 147 | invokeBeanFactoryPostProcessors(beanFactory); 148 | } 149 | 150 | private void delayedRefresh() throws BeansException, IllegalStateException { 151 | super.refresh(); 152 | } 153 | 154 | @Override 155 | public void refresh() { 156 | } 157 | 158 | @Override 159 | protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) { 160 | if (this.partiallyRefreshed.compareAndSet(false, true)) { 161 | super.invokeBeanFactoryPostProcessors(beanFactory); 162 | } 163 | } 164 | 165 | } 166 | 167 | private static final class ContextRefreshingProvisionListener implements ProvisionListener { 168 | 169 | private final PartiallyRefreshableApplicationContext context; 170 | 171 | private final AtomicBoolean initialized = new AtomicBoolean(false); 172 | 173 | private ContextRefreshingProvisionListener(PartiallyRefreshableApplicationContext context) { 174 | this.context = context; 175 | } 176 | 177 | @Override 178 | public void onProvision(ProvisionInvocation provision) { 179 | if (!this.initialized.getAndSet(true) && !this.context.isActive()) { 180 | this.context.delayedRefresh(); 181 | } 182 | provision.provision(); 183 | } 184 | 185 | } 186 | 187 | } 188 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/guice/module/BindingTypeMatcher.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012-2013 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.guice.module; 18 | 19 | import java.lang.reflect.Type; 20 | 21 | /** 22 | * Utility to check whether a binding matches the given name and type. 23 | * 24 | * @author Dave Syer 25 | * 26 | */ 27 | public interface BindingTypeMatcher { 28 | 29 | boolean matches(String name, Type type); 30 | 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/guice/module/GuiceAutowireCandidateResolver.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.guice.module; 18 | 19 | import java.lang.reflect.Type; 20 | import java.util.Collection; 21 | import java.util.Map; 22 | import java.util.Optional; 23 | 24 | import com.google.inject.BindingAnnotation; 25 | import com.google.inject.Injector; 26 | import com.google.inject.Key; 27 | import com.google.inject.name.Names; 28 | import jakarta.inject.Provider; 29 | import org.apache.commons.logging.Log; 30 | import org.apache.commons.logging.LogFactory; 31 | 32 | import org.springframework.aop.TargetSource; 33 | import org.springframework.aop.framework.ProxyFactory; 34 | import org.springframework.beans.factory.NoSuchBeanDefinitionException; 35 | import org.springframework.beans.factory.annotation.Qualifier; 36 | import org.springframework.beans.factory.config.DependencyDescriptor; 37 | import org.springframework.beans.factory.support.DefaultListableBeanFactory; 38 | import org.springframework.context.annotation.ContextAnnotationAutowireCandidateResolver; 39 | import org.springframework.util.Assert; 40 | 41 | /** 42 | * Extension of {@link ContextAnnotationAutowireCandidateResolver} providing support for 43 | * exposing beans as just in time bindings. 44 | * 45 | * @author Dave Syer 46 | * @author Taylor Wicksell 47 | * @author Howard Yuan 48 | * 49 | */ 50 | class GuiceAutowireCandidateResolver extends ContextAnnotationAutowireCandidateResolver { 51 | 52 | private Provider injectorProvider; 53 | 54 | private final Log logger = LogFactory.getLog(getClass()); 55 | 56 | GuiceAutowireCandidateResolver(Provider injectorProvider) { 57 | this.injectorProvider = injectorProvider; 58 | addQualifierType(BindingAnnotation.class); 59 | } 60 | 61 | @Override 62 | public Object getLazyResolutionProxyIfNecessary(DependencyDescriptor descriptor, String beanName) { 63 | return (isLazy(descriptor, beanName) ? buildLazyResolutionProxy(descriptor, beanName) : null); 64 | } 65 | 66 | protected boolean isLazy(DependencyDescriptor descriptor, String beanName) { 67 | Assert.state(getBeanFactory() instanceof DefaultListableBeanFactory, 68 | "BeanFactory needs to be a DefaultListableBeanFactory"); 69 | final DefaultListableBeanFactory beanFactory = (DefaultListableBeanFactory) getBeanFactory(); 70 | 71 | if (isCollectionType(descriptor.getDependencyType())) { 72 | return false; 73 | } 74 | 75 | if (super.isLazy(descriptor)) { 76 | return true; 77 | } 78 | 79 | try { 80 | beanFactory.doResolveDependency(descriptor, beanName, null, null); 81 | } 82 | catch (NoSuchBeanDefinitionException ex) { 83 | if (ex.getResolvableType() != null) { 84 | this.logger.debug(String.format("Using just in time binding for %s in bean: %s", 85 | ex.getResolvableType().getType().getTypeName(), beanName)); 86 | } 87 | return true; 88 | } 89 | 90 | return false; 91 | } 92 | 93 | protected Object buildLazyResolutionProxy(final DependencyDescriptor descriptor, final String beanName) { 94 | Assert.state(getBeanFactory() instanceof DefaultListableBeanFactory, 95 | "BeanFactory needs to be a DefaultListableBeanFactory"); 96 | final DefaultListableBeanFactory beanFactory = (DefaultListableBeanFactory) getBeanFactory(); 97 | TargetSource ts = new TargetSource() { 98 | private Optional isGuiceResolvable = Optional.empty(); 99 | 100 | @Override 101 | public Class getTargetClass() { 102 | return descriptor.getDependencyType(); 103 | } 104 | 105 | @Override 106 | public boolean isStatic() { 107 | return false; 108 | } 109 | 110 | @Override 111 | public Object getTarget() { 112 | Object target = null; 113 | if (this.isGuiceResolvable.isPresent() && this.isGuiceResolvable.get()) { 114 | target = targetGuiceObject(); 115 | } 116 | else { 117 | try { 118 | target = beanFactory.doResolveDependency(descriptor, beanName, null, null); 119 | } 120 | catch (NoSuchBeanDefinitionException ex) { 121 | target = targetGuiceObject(); 122 | this.isGuiceResolvable = Optional.of(true); 123 | } 124 | } 125 | if (target == null) { 126 | throw new NoSuchBeanDefinitionException(descriptor.getDependencyType(), 127 | "Optional dependency not present for lazy injection point"); 128 | } 129 | return target; 130 | } 131 | 132 | private Object targetGuiceObject() { 133 | Key key = guiceInstanceResolverKey(); 134 | return GuiceAutowireCandidateResolver.this.injectorProvider.get().getInstance(key); 135 | } 136 | 137 | private Key guiceInstanceResolverKey() { 138 | Type type = descriptor.getResolvableType().getType(); 139 | 140 | Qualifier qualifierValue = qualifierBean(descriptor); 141 | if (qualifierValue != null) { 142 | return Key.get(type, Names.named(qualifierValue.value())); 143 | } 144 | return Key.get(type); 145 | } 146 | 147 | private Qualifier qualifierBean(DependencyDescriptor descriptor) { 148 | if (descriptor.getField() != null) { 149 | return descriptor.getField().getAnnotation(Qualifier.class); 150 | } 151 | if (descriptor.getMethodParameter() != null) { 152 | return descriptor.getMethodParameter().getParameterAnnotation(Qualifier.class); 153 | } 154 | return null; 155 | } 156 | 157 | @Override 158 | public void releaseTarget(Object target) { 159 | } 160 | }; 161 | try { 162 | ProxyFactory pf = new ProxyFactory(); 163 | pf.setTargetSource(ts); 164 | Class dependencyType = descriptor.getDependencyType(); 165 | if (dependencyType.isInterface()) { 166 | pf.addInterface(dependencyType); 167 | } 168 | return pf.getProxy(beanFactory.getBeanClassLoader()); 169 | } 170 | catch (Exception ex) { 171 | this.logger.debug("Failed to build lazy resolution proxy to Guice", ex); 172 | } 173 | return null; 174 | } 175 | 176 | private boolean isCollectionType(Class type) { 177 | return Collection.class.isAssignableFrom(type) || Map.class == type; 178 | } 179 | 180 | } 181 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/guice/module/GuiceModuleMetadata.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012-2013 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.guice.module; 18 | 19 | import java.io.IOException; 20 | import java.lang.reflect.Modifier; 21 | import java.lang.reflect.ParameterizedType; 22 | import java.lang.reflect.Type; 23 | import java.util.HashSet; 24 | import java.util.Set; 25 | import java.util.regex.Pattern; 26 | 27 | import org.springframework.beans.factory.DisposableBean; 28 | import org.springframework.beans.factory.InitializingBean; 29 | import org.springframework.core.ResolvableType; 30 | import org.springframework.core.type.classreading.CachingMetadataReaderFactory; 31 | import org.springframework.core.type.classreading.MetadataReader; 32 | import org.springframework.core.type.classreading.MetadataReaderFactory; 33 | import org.springframework.core.type.filter.TypeFilter; 34 | import org.springframework.guice.annotation.GuiceModule; 35 | import org.springframework.util.PatternMatchUtils; 36 | 37 | /** 38 | * Encapsulates some metadata about a Guice module that is to be created from a Spring 39 | * application context. Can be used directly as a @Bean, but it is easier to 40 | * just add @ {@link GuiceModule} to your @Configuration. 41 | * 42 | * @author Dave Syer 43 | * 44 | */ 45 | public class GuiceModuleMetadata implements BindingTypeMatcher { 46 | 47 | private TypeFilter[] includeFilters; 48 | 49 | private TypeFilter[] excludeFilters; 50 | 51 | private Pattern[] includePatterns; 52 | 53 | private Pattern[] excludePatterns; 54 | 55 | private String[] includeNames; 56 | 57 | private String[] excludeNames; 58 | 59 | private Set> infrastructureTypes = new HashSet>(); 60 | 61 | { 62 | this.infrastructureTypes.add(InitializingBean.class); 63 | this.infrastructureTypes.add(DisposableBean.class); 64 | } 65 | 66 | private MetadataReaderFactory metadataReaderFactory = new CachingMetadataReaderFactory(); 67 | 68 | public GuiceModuleMetadata include(String... filters) { 69 | this.includeNames = filters; 70 | return this; 71 | } 72 | 73 | public GuiceModuleMetadata exclude(String... filters) { 74 | this.excludeNames = filters; 75 | return this; 76 | } 77 | 78 | public GuiceModuleMetadata include(Pattern... filters) { 79 | this.includePatterns = filters; 80 | return this; 81 | } 82 | 83 | public GuiceModuleMetadata exclude(Pattern... filters) { 84 | this.excludePatterns = filters; 85 | return this; 86 | } 87 | 88 | public GuiceModuleMetadata include(TypeFilter... filters) { 89 | this.includeFilters = filters; 90 | return this; 91 | } 92 | 93 | public GuiceModuleMetadata exclude(TypeFilter... filters) { 94 | this.excludeFilters = filters; 95 | return this; 96 | } 97 | 98 | @Override 99 | public boolean matches(String name, Type type) { 100 | Type rawType = (type instanceof ParameterizedType) ? ((ParameterizedType) type).getRawType() : type; 101 | return matches(name) && matches(rawType); 102 | } 103 | 104 | private boolean matches(String name) { 105 | if (this.includePatterns != null) { 106 | for (Pattern filter : this.includePatterns) { 107 | if (!filter.matcher(name).matches()) { 108 | return false; 109 | } 110 | } 111 | } 112 | if (this.excludePatterns != null) { 113 | for (Pattern filter : this.excludePatterns) { 114 | if (filter.matcher(name).matches()) { 115 | return false; 116 | } 117 | } 118 | } 119 | if (this.includeNames != null && this.includeNames.length > 0) { 120 | if (!PatternMatchUtils.simpleMatch(this.includeNames, name)) { 121 | return false; 122 | } 123 | } 124 | if (this.excludeNames != null && this.excludeNames.length > 0) { 125 | return !PatternMatchUtils.simpleMatch(this.excludeNames, name); 126 | } 127 | return true; 128 | } 129 | 130 | private boolean matches(Type type) { 131 | if (this.infrastructureTypes.contains(type)) { 132 | return false; 133 | } 134 | 135 | if (!visible(type)) { 136 | return false; 137 | } 138 | 139 | if (this.includeFilters != null) { 140 | try { 141 | MetadataReader reader = this.metadataReaderFactory.getMetadataReader(type.getTypeName()); 142 | for (TypeFilter filter : this.includeFilters) { 143 | if (!filter.match(reader, this.metadataReaderFactory)) { 144 | return false; 145 | } 146 | } 147 | } 148 | catch (IOException ex) { 149 | throw new IllegalStateException("Cannot read metadata for class " + type, ex); 150 | } 151 | } 152 | if (this.excludeFilters != null) { 153 | try { 154 | MetadataReader reader = this.metadataReaderFactory.getMetadataReader(type.getTypeName()); 155 | for (TypeFilter filter : this.excludeFilters) { 156 | if (filter.match(reader, this.metadataReaderFactory)) { 157 | return false; 158 | } 159 | } 160 | } 161 | catch (IOException ex) { 162 | throw new IllegalStateException("Cannot read metadata for class " + type, ex); 163 | } 164 | } 165 | return true; 166 | } 167 | 168 | private boolean visible(Type type) { 169 | Class cls = ResolvableType.forType(type).resolve(); 170 | while (cls != null && cls != Object.class) { 171 | if (!Modifier.isInterface(cls.getModifiers()) && !Modifier.isPublic(cls.getModifiers()) 172 | && !Modifier.isProtected(cls.getModifiers())) { 173 | return false; 174 | } 175 | cls = cls.getDeclaringClass(); 176 | } 177 | return true; 178 | } 179 | 180 | } 181 | -------------------------------------------------------------------------------- /src/main/resources/META-INF/additional-spring-configuration-metadata.json: -------------------------------------------------------------------------------- 1 | { 2 | "properties": [ 3 | { 4 | "name": "spring.guice.dedup", 5 | "type": "java.lang.Boolean", 6 | "description": "When using `@EnableGuiceModules`, if a Spring Bean and a Guice Binding both exist for the same type and Qualifier, the Spring Bean will be kept and the Guice Binding discarded.", 7 | "defaultValue": "false" 8 | }, 9 | { 10 | "name": "spring.guice.autowireJIT", 11 | "type": "java.lang.Boolean", 12 | "description": "When enabled, beans without explicit definitions will be created using Guice just-in-time bindings. Otherwise, it will fail with UnsatisfiedDependencyException.", 13 | "defaultValue": "true" 14 | } 15 | ] 16 | } -------------------------------------------------------------------------------- /src/test/java/org/springframework/guice/AbstractCompleteWiringTests.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014-2022 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.guice; 18 | 19 | import com.google.inject.Injector; 20 | import com.google.inject.Key; 21 | import com.google.inject.TypeLiteral; 22 | import com.google.inject.name.Names; 23 | import jakarta.inject.Inject; 24 | import jakarta.inject.Named; 25 | import org.junit.jupiter.api.BeforeEach; 26 | import org.junit.jupiter.api.Test; 27 | 28 | import static org.assertj.core.api.Assertions.assertThat; 29 | 30 | public abstract class AbstractCompleteWiringTests { 31 | 32 | private Injector injector; 33 | 34 | @BeforeEach 35 | public void init() { 36 | this.injector = createInjector(); 37 | } 38 | 39 | protected abstract Injector createInjector(); 40 | 41 | @Test 42 | public void injectInstance() { 43 | Bar bar = new Bar(); 44 | this.injector.injectMembers(bar); 45 | assertThat(bar.service).isNotNull(); 46 | } 47 | 48 | @Test 49 | public void memberInjector() { 50 | Bar bar = new Bar(); 51 | this.injector.getMembersInjector(Bar.class).injectMembers(bar); 52 | assertThat(bar.service).isNotNull(); 53 | } 54 | 55 | @Test 56 | public void getInstanceUnbound() { 57 | assertThat(this.injector.getInstance(Foo.class)).isNotNull(); 58 | } 59 | 60 | @Test 61 | public void getInstanceUnboundWithDependency() { 62 | assertThat(this.injector.getInstance(Bar.class).service).isNotNull(); 63 | } 64 | 65 | @Test 66 | public void getInstanceBound() { 67 | assertThat(this.injector.getInstance(Service.class)).isNotNull(); 68 | } 69 | 70 | @Test 71 | public void getInstanceBoundWithNoInterface() { 72 | Baz instance = this.injector.getInstance(Baz.class); 73 | assertThat(instance).isNotNull(); 74 | assertThat(this.injector.getInstance(Baz.class)).isEqualTo(instance); 75 | } 76 | 77 | @Test 78 | public void getProviderUnbound() { 79 | assertThat(this.injector.getProvider(Foo.class).get()).isNotNull(); 80 | } 81 | 82 | @Test 83 | public void getProviderBound() { 84 | assertThat(this.injector.getProvider(Service.class).get()).isNotNull(); 85 | } 86 | 87 | @Test 88 | public void getNamedInstance() { 89 | assertThat(this.injector.getInstance(Key.get(Thang.class, Names.named("thing")))).isNotNull(); 90 | } 91 | 92 | @Test 93 | public void getNamedInjectedInstance() { 94 | Thang thang = this.injector.getInstance(Thing.class).thang; 95 | assertThat(thang).isNotNull(); 96 | } 97 | 98 | @Test 99 | public void getParameterizedType() { 100 | Parameterized instance = this.injector.getInstance(Key.get(new TypeLiteral>() { 101 | })); 102 | assertThat(instance).isNotNull(); 103 | } 104 | 105 | public interface Service { 106 | 107 | } 108 | 109 | public static class MyService implements Service { 110 | 111 | } 112 | 113 | public static class Foo { 114 | 115 | @Inject 116 | public Foo(Service service) { 117 | } 118 | 119 | } 120 | 121 | public static class Bar { 122 | 123 | private Service service; 124 | 125 | @Inject 126 | public void setService(Service service) { 127 | this.service = service; 128 | } 129 | 130 | } 131 | 132 | public static class Baz { 133 | 134 | @Inject 135 | public Baz(Service service) { 136 | } 137 | 138 | } 139 | 140 | public static class Thing { 141 | 142 | private Thang thang; 143 | 144 | @Inject 145 | public void setThang(@Named("thing") Thang thang) { 146 | this.thang = thang; 147 | } 148 | 149 | } 150 | 151 | public static class Thang { 152 | 153 | } 154 | 155 | public interface Parameterized { 156 | 157 | } 158 | 159 | } 160 | -------------------------------------------------------------------------------- /src/test/java/org/springframework/guice/AdhocTestSuite.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012-2015 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.guice; 18 | 19 | import org.junit.jupiter.api.Disabled; 20 | import org.junit.platform.suite.api.SelectClasses; 21 | import org.junit.platform.suite.api.Suite; 22 | 23 | import org.springframework.guice.annotation.EnableGuiceModulesTests; 24 | 25 | /** 26 | * A test suite for probing weird ordering problems in the tests. 27 | * 28 | * @author Dave Syer 29 | */ 30 | @Suite 31 | @SelectClasses({ MapBindingDeduplicationTests.class, BindingDeduplicationTests.class, EnableGuiceModulesTests.class }) 32 | @Disabled 33 | public class AdhocTestSuite { 34 | 35 | } 36 | -------------------------------------------------------------------------------- /src/test/java/org/springframework/guice/BeanPostProcessorTests.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018-2022 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.guice; 18 | 19 | import com.google.inject.AbstractModule; 20 | import com.google.inject.Module; 21 | import jakarta.inject.Inject; 22 | import org.junit.jupiter.api.Test; 23 | 24 | import org.springframework.beans.BeansException; 25 | import org.springframework.beans.factory.config.BeanPostProcessor; 26 | import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; 27 | import org.springframework.beans.factory.support.BeanDefinitionBuilder; 28 | import org.springframework.beans.factory.support.BeanDefinitionRegistry; 29 | import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor; 30 | import org.springframework.context.annotation.AnnotationConfigApplicationContext; 31 | import org.springframework.context.annotation.Bean; 32 | import org.springframework.context.annotation.Configuration; 33 | import org.springframework.guice.annotation.EnableGuiceModules; 34 | 35 | import static org.assertj.core.api.Assertions.assertThat; 36 | 37 | public class BeanPostProcessorTests { 38 | 39 | /** 40 | * Verify BeanPostProcessor's such as Spring Boot's 41 | * ConfigurationPropertiesBindingPostProcessor are applied. 42 | */ 43 | @Test 44 | public void testBeanPostProcessorsApplied() { 45 | AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext( 46 | BeanPostProcessorTestConfig.class); 47 | PostProcessedBean postProcessedBean = context.getBean(PostProcessedBean.class); 48 | assertThat(postProcessedBean.postProcessed).isTrue(); 49 | GuiceBeanThatWantsPostProcessedBean guiceBean1 = context.getBean(GuiceBeanThatWantsPostProcessedBean.class); 50 | assertThat(guiceBean1.ppb.postProcessed).isTrue(); 51 | GuiceBeanThatWantsSpringBean guiceBean2 = context.getBean(GuiceBeanThatWantsSpringBean.class); 52 | assertThat(guiceBean2.springBean.ppb.postProcessed).isTrue(); 53 | context.close(); 54 | } 55 | 56 | public static class PostProcessedBean { 57 | 58 | Boolean postProcessed = false; 59 | 60 | } 61 | 62 | public static class SpringBeanThatWantsPostProcessedBean { 63 | 64 | PostProcessedBean ppb; 65 | 66 | public SpringBeanThatWantsPostProcessedBean(PostProcessedBean ppb) { 67 | this.ppb = ppb; 68 | } 69 | 70 | } 71 | 72 | public static class GuiceBeanThatWantsPostProcessedBean { 73 | 74 | PostProcessedBean ppb; 75 | 76 | @Inject 77 | public GuiceBeanThatWantsPostProcessedBean(PostProcessedBean ppb) { 78 | this.ppb = ppb; 79 | } 80 | 81 | } 82 | 83 | public static class GuiceBeanThatWantsSpringBean { 84 | 85 | SpringBeanThatWantsPostProcessedBean springBean; 86 | 87 | @Inject 88 | public GuiceBeanThatWantsSpringBean(SpringBeanThatWantsPostProcessedBean springBean) { 89 | this.springBean = springBean; 90 | } 91 | 92 | } 93 | 94 | @EnableGuiceModules 95 | @Configuration 96 | static class BeanPostProcessorTestConfig { 97 | 98 | @Bean 99 | static PostProcessorRegistrar postProcessorRegistrar() { 100 | return new PostProcessorRegistrar(); 101 | } 102 | 103 | @Bean 104 | PostProcessedBean postProcessedBean() { 105 | return new PostProcessedBean(); 106 | } 107 | 108 | @Bean 109 | SpringBeanThatWantsPostProcessedBean springBean(PostProcessedBean ppb) { 110 | return new SpringBeanThatWantsPostProcessedBean(ppb); 111 | } 112 | 113 | @Bean 114 | static Module someGuiceModule() { 115 | return new AbstractModule() { 116 | 117 | @Override 118 | protected void configure() { 119 | binder().requireExplicitBindings(); 120 | bind(GuiceBeanThatWantsPostProcessedBean.class).asEagerSingleton(); 121 | bind(GuiceBeanThatWantsSpringBean.class).asEagerSingleton(); 122 | } 123 | }; 124 | } 125 | 126 | public static class PostProcessorRegistrar implements BeanDefinitionRegistryPostProcessor { 127 | 128 | @Override 129 | public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException { 130 | BeanDefinitionBuilder bean = BeanDefinitionBuilder.genericBeanDefinition(TestBeanPostProcessor.class); 131 | registry.registerBeanDefinition("postProcessor", bean.getBeanDefinition()); 132 | } 133 | 134 | @Override 135 | public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { 136 | } 137 | 138 | } 139 | 140 | public static class TestBeanPostProcessor implements BeanPostProcessor { 141 | 142 | @Override 143 | public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { 144 | if (bean instanceof PostProcessedBean) { 145 | ((PostProcessedBean) bean).postProcessed = true; 146 | } 147 | return bean; 148 | } 149 | 150 | @Override 151 | public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { 152 | return bean; 153 | } 154 | 155 | } 156 | 157 | } 158 | 159 | } 160 | -------------------------------------------------------------------------------- /src/test/java/org/springframework/guice/BindingDeduplicationTests.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018-2022 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.guice; 18 | 19 | import com.google.inject.AbstractModule; 20 | import com.google.inject.CreationException; 21 | import com.google.inject.Module; 22 | import com.google.inject.Scopes; 23 | import com.google.inject.multibindings.Multibinder; 24 | import com.google.inject.multibindings.OptionalBinder; 25 | import com.google.inject.name.Names; 26 | import org.junit.jupiter.api.AfterEach; 27 | import org.junit.jupiter.api.BeforeEach; 28 | import org.junit.jupiter.api.Test; 29 | 30 | import org.springframework.beans.factory.NoUniqueBeanDefinitionException; 31 | import org.springframework.context.annotation.AnnotationConfigApplicationContext; 32 | import org.springframework.context.annotation.Bean; 33 | import org.springframework.context.annotation.Configuration; 34 | import org.springframework.guice.annotation.EnableGuiceModules; 35 | 36 | import static org.assertj.core.api.Assertions.assertThat; 37 | import static org.assertj.core.api.Assertions.assertThatExceptionOfType; 38 | 39 | public class BindingDeduplicationTests { 40 | 41 | @BeforeEach 42 | public void setup() { 43 | System.setProperty("spring.guice.dedup", "true"); 44 | } 45 | 46 | @AfterEach 47 | public void cleanUp() { 48 | System.clearProperty("spring.guice.dedup"); 49 | } 50 | 51 | @Test 52 | public void verifyNoDuplicateBindingErrorWhenDedupeEnabled() { 53 | try (AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext( 54 | BindingDeduplicationTestsConfig.class)) { 55 | Dependency dependency = context.getBean(Dependency.class); 56 | assertThat(dependency).isNotNull(); 57 | 58 | OptionalDependency optionalDependency = context.getBean(OptionalDependency.class); 59 | assertThat(optionalDependency).isNotNull(); 60 | } 61 | } 62 | 63 | @Test 64 | public void annotatedBindingDoesNotDuplicate() { 65 | try (AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext( 66 | BindingDeduplicationTestsConfig.class)) { 67 | FirstInterface firstInterface = context.getBean(FirstInterface.class); 68 | assertThat(firstInterface).isNotNull(); 69 | } 70 | } 71 | 72 | @Test 73 | public void untargettedBindingDoesNotDuplicate() { 74 | try (AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext( 75 | BindingDeduplicationTestsConfig.class)) { 76 | UntargettedDependency untargettedDependency = context.getBean(UntargettedDependency.class); 77 | assertThat(untargettedDependency).isNotNull(); 78 | } 79 | } 80 | 81 | @Test 82 | public void setBindingDoesNotDuplicate() { 83 | try (AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext( 84 | BindingDeduplicationTestsConfig.class)) { 85 | SetProvided setProvided = context.getBean(SetProvided.class); 86 | assertThat(setProvided).isNotNull(); 87 | } 88 | } 89 | 90 | @Test 91 | public void springBindingIsDuplicated() { 92 | AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext( 93 | BindingDeduplicationTestsConfig.class); 94 | 95 | assertThatExceptionOfType(NoUniqueBeanDefinitionException.class) 96 | .isThrownBy(() -> context.getBean(String.class)); 97 | 98 | context.close(); 99 | } 100 | 101 | @Test 102 | public void verifyDuplicateBindingErrorWhenDedupeNotEnabled() { 103 | System.setProperty("spring.guice.dedup", "false"); 104 | assertThatExceptionOfType(CreationException.class).isThrownBy(() -> { 105 | AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext( 106 | BindingDeduplicationTestsConfig.class); 107 | context.close(); 108 | }); 109 | } 110 | 111 | public interface Dependency { 112 | 113 | } 114 | 115 | private static class PrivateDependency implements Dependency { 116 | 117 | } 118 | 119 | public static class SomeSingleton { 120 | 121 | } 122 | 123 | public interface OptionalDependency { 124 | 125 | } 126 | 127 | public static class SomeOptionalDependency implements OptionalDependency { 128 | 129 | } 130 | 131 | interface FirstInterface { 132 | 133 | } 134 | 135 | interface SecondInterface { 136 | 137 | } 138 | 139 | static class MultiInterfaceSingleton implements FirstInterface, SecondInterface { 140 | 141 | } 142 | 143 | static class UntargettedDependency { 144 | 145 | } 146 | 147 | interface SetProvided { 148 | 149 | } 150 | 151 | public static class SomeSetProvided implements SetProvided { 152 | 153 | } 154 | 155 | @EnableGuiceModules 156 | @Configuration 157 | static class BindingDeduplicationTestsConfig { 158 | 159 | @Bean 160 | SomeSingleton someSingleton() { 161 | return new SomeSingleton(); 162 | } 163 | 164 | @Bean 165 | PrivateDependency privateDependency() { 166 | return new PrivateDependency(); 167 | } 168 | 169 | @Bean 170 | OptionalDependency someOptionalDependency() { 171 | return new SomeOptionalDependency(); 172 | } 173 | 174 | @Bean 175 | String barString() { 176 | return "bar"; 177 | } 178 | 179 | @Bean 180 | SomeSetProvided someSetProvided() { 181 | return new SomeSetProvided(); 182 | } 183 | 184 | @Bean 185 | static Module module() { 186 | return new AbstractModule() { 187 | @Override 188 | protected void configure() { 189 | bind(Dependency.class).to(PrivateDependency.class); 190 | bind(SomeSingleton.class).asEagerSingleton(); 191 | 192 | OptionalBinder.newOptionalBinder(binder(), OptionalDependency.class).setDefault() 193 | .to(SomeOptionalDependency.class); 194 | 195 | Multibinder setBinder = Multibinder.newSetBinder(binder(), SetProvided.class); 196 | setBinder.addBinding().toInstance(new SomeSetProvided()); 197 | 198 | bind(UntargettedDependency.class); 199 | 200 | // Untargetted binding to provide a singleton for the interface 201 | // bindings 202 | bind(MultiInterfaceSingleton.class).in(Scopes.SINGLETON); 203 | bind(FirstInterface.class).to(MultiInterfaceSingleton.class).in(Scopes.SINGLETON); 204 | bind(SecondInterface.class).to(MultiInterfaceSingleton.class).in(Scopes.SINGLETON); 205 | 206 | bind(String.class).annotatedWith(Names.named("fooString")).toInstance("foo"); 207 | } 208 | }; 209 | } 210 | 211 | } 212 | 213 | } 214 | -------------------------------------------------------------------------------- /src/test/java/org/springframework/guice/DuplicateNamesDifferentTypesTests.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018-2022 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.guice; 18 | 19 | import com.google.inject.AbstractModule; 20 | import com.google.inject.Module; 21 | import com.google.inject.Provides; 22 | import com.google.inject.name.Named; 23 | import com.google.inject.name.Names; 24 | import org.junit.jupiter.api.Test; 25 | 26 | import org.springframework.beans.factory.annotation.Autowired; 27 | import org.springframework.beans.factory.annotation.BeanFactoryAnnotationUtils; 28 | import org.springframework.beans.factory.annotation.Qualifier; 29 | import org.springframework.context.annotation.AnnotationConfigApplicationContext; 30 | import org.springframework.context.annotation.Bean; 31 | import org.springframework.context.annotation.Configuration; 32 | import org.springframework.guice.annotation.EnableGuiceModules; 33 | 34 | import static org.assertj.core.api.Assertions.assertThat; 35 | 36 | public class DuplicateNamesDifferentTypesTests { 37 | 38 | @Test 39 | public void verifyNoDuplicateBindingErrorWhenDedupeEnabled() { 40 | AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext( 41 | DuplicateNamesDifferentTypesTestsConfig.class); 42 | 43 | // Check Guice @Named 44 | assertThat(context.getBean(SomeNamedDepWithType1.class)).isNotNull(); 45 | assertThat(context.getBean(SomeNamedDepWithType2.class)).isNotNull(); 46 | assertThat(BeanFactoryAnnotationUtils.qualifiedBeanOfType(context.getBeanFactory(), SomeNamedDepWithType1.class, 47 | "sameNameDifferentType")).isNotNull(); 48 | 49 | // Check jakarta @Named 50 | assertThat(context.getBean(SomeJakartaNamedDepWithType1.class)).isNotNull(); 51 | assertThat(context.getBean(SomeJakartaNamedDepWithType2.class)).isNotNull(); 52 | assertThat(BeanFactoryAnnotationUtils.qualifiedBeanOfType(context.getBeanFactory(), 53 | SomeJakartaNamedDepWithType1.class, "sameJakartaName")).isNotNull(); 54 | context.getBeansOfType(SomeJakartaNamedDepWithType1.class); 55 | 56 | context.close(); 57 | } 58 | 59 | public static class SomeNamedDepWithType1 { 60 | 61 | } 62 | 63 | public static class SomeNamedDepWithType2 { 64 | 65 | } 66 | 67 | public static class SomeJakartaNamedDepWithType1 { 68 | 69 | } 70 | 71 | public static class SomeJakartaNamedDepWithType2 { 72 | 73 | } 74 | 75 | public static class SomeClassWithDeps { 76 | 77 | @Autowired 78 | @Qualifier("sameJakartaName2") 79 | SomeJakartaNamedDepWithType1 qualified; 80 | 81 | @Autowired 82 | @Named("sameJakartaName2") 83 | SomeJakartaNamedDepWithType1 named; 84 | 85 | @Autowired 86 | @jakarta.inject.Named("sameJakartaName2") 87 | SomeJakartaNamedDepWithType1 jakartaNamed; 88 | 89 | } 90 | 91 | @EnableGuiceModules 92 | @Configuration 93 | static class DuplicateNamesDifferentTypesTestsConfig { 94 | 95 | @Bean 96 | static Module module() { 97 | return new AbstractModule() { 98 | @Override 99 | protected void configure() { 100 | bind(SomeNamedDepWithType1.class).annotatedWith(Names.named("sameNameDifferentType")) 101 | .to(SomeNamedDepWithType1.class); 102 | bind(SomeNamedDepWithType2.class).annotatedWith(Names.named("sameNameDifferentType")) 103 | .to(SomeNamedDepWithType2.class); 104 | } 105 | 106 | @Provides 107 | @Named("sameJakartaName") 108 | SomeJakartaNamedDepWithType1 someJakartaNamedDepWithType1() { 109 | return new SomeJakartaNamedDepWithType1(); 110 | } 111 | 112 | @Provides 113 | @Named("sameJakartaName") 114 | SomeJakartaNamedDepWithType2 someJakartaNamedDepWithType2() { 115 | return new SomeJakartaNamedDepWithType2(); 116 | } 117 | }; 118 | } 119 | 120 | } 121 | 122 | } 123 | -------------------------------------------------------------------------------- /src/test/java/org/springframework/guice/ElementVisitorTests.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018-2022 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.guice; 18 | 19 | import java.util.List; 20 | 21 | import com.google.inject.AbstractModule; 22 | import com.google.inject.Guice; 23 | import com.google.inject.Injector; 24 | import com.google.inject.Module; 25 | import com.google.inject.Stage; 26 | import com.google.inject.spi.Element; 27 | import com.google.inject.spi.Elements; 28 | import jakarta.inject.Inject; 29 | import org.junit.jupiter.api.AfterAll; 30 | import org.junit.jupiter.api.BeforeAll; 31 | import org.junit.jupiter.api.Test; 32 | 33 | import org.springframework.context.annotation.AnnotationConfigApplicationContext; 34 | import org.springframework.context.annotation.Bean; 35 | import org.springframework.context.annotation.Configuration; 36 | import org.springframework.guice.annotation.EnableGuiceModules; 37 | import org.springframework.guice.annotation.InjectorFactory; 38 | 39 | import static org.assertj.core.api.Assertions.assertThat; 40 | 41 | public class ElementVisitorTests { 42 | 43 | private static AnnotationConfigApplicationContext context; 44 | 45 | @BeforeAll 46 | public static void init() { 47 | System.setProperty("spring.guice.dedup", "true"); 48 | context = new AnnotationConfigApplicationContext(ElementVisitorTestConfig.class); 49 | } 50 | 51 | @AfterAll 52 | public static void cleanup() { 53 | System.clearProperty("spring.guice.dedup"); 54 | if (context != null) { 55 | context.close(); 56 | } 57 | } 58 | 59 | @Test 60 | public void verifySpringModuleDoesNotBreakWhenUsingElementVisitors() { 61 | ElementVisitorTestSpringBean testSpringBean = context.getBean(ElementVisitorTestSpringBean.class); 62 | assertThat(testSpringBean.toString()).isEqualTo("spring created"); 63 | ElementVisitorTestGuiceBean testGuiceBean = context.getBean(ElementVisitorTestGuiceBean.class); 64 | assertThat(testGuiceBean.toString()).isEqualTo("spring created"); 65 | } 66 | 67 | public static class ElementVisitorTestSpringBean { 68 | 69 | @Override 70 | public String toString() { 71 | return "default"; 72 | } 73 | 74 | } 75 | 76 | public static class ElementVisitorTestGuiceBean { 77 | 78 | @Inject 79 | ElementVisitorTestSpringBean springBean; 80 | 81 | @Override 82 | public String toString() { 83 | return this.springBean.toString(); 84 | } 85 | 86 | } 87 | 88 | public static class DuplicateBean { 89 | 90 | } 91 | 92 | @EnableGuiceModules 93 | @Configuration 94 | static class ElementVisitorTestConfig { 95 | 96 | @Bean 97 | ElementVisitorTestSpringBean testBean() { 98 | return new ElementVisitorTestSpringBean() { 99 | @Override 100 | public String toString() { 101 | return "spring created"; 102 | } 103 | }; 104 | } 105 | 106 | @Bean 107 | static Module module() { 108 | return new AbstractModule() { 109 | @Override 110 | protected void configure() { 111 | binder().requireExplicitBindings(); 112 | bind(ElementVisitorTestGuiceBean.class).asEagerSingleton(); 113 | } 114 | }; 115 | } 116 | 117 | @Bean 118 | InjectorFactory injectorFactory() { 119 | return new InjectorFactory() { 120 | @Override 121 | public Injector createInjector(List modules) { 122 | List elements = Elements.getElements(Stage.TOOL, modules); 123 | return Guice.createInjector(Stage.PRODUCTION, Elements.getModule(elements)); 124 | } 125 | }; 126 | } 127 | 128 | @Bean 129 | DuplicateBean dupeBean1() { 130 | return new DuplicateBean(); 131 | } 132 | 133 | @Bean 134 | DuplicateBean dupeBean2() { 135 | return new DuplicateBean(); 136 | } 137 | 138 | } 139 | 140 | } 141 | -------------------------------------------------------------------------------- /src/test/java/org/springframework/guice/GuiceWiringTests.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2013-2014 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.guice; 18 | 19 | import com.google.inject.AbstractModule; 20 | import com.google.inject.Guice; 21 | import com.google.inject.Injector; 22 | import com.google.inject.TypeLiteral; 23 | import com.google.inject.name.Names; 24 | import jakarta.inject.Singleton; 25 | 26 | /** 27 | * @author Dave Syer 28 | * 29 | */ 30 | public class GuiceWiringTests extends AbstractCompleteWiringTests { 31 | 32 | @Override 33 | protected Injector createInjector() { 34 | Injector app = Guice.createInjector(new TestConfig()); 35 | return app; 36 | } 37 | 38 | public static class TestConfig extends AbstractModule { 39 | 40 | @Override 41 | protected void configure() { 42 | bind(Service.class).to(MyService.class); 43 | bind(Baz.class).in(Singleton.class); 44 | bind(Thang.class).annotatedWith(Names.named("thing")).to(Thang.class); 45 | bind(new TypeLiteral>() { 46 | }).toInstance(new Parameterized() { 47 | }); 48 | } 49 | 50 | } 51 | 52 | } 53 | -------------------------------------------------------------------------------- /src/test/java/org/springframework/guice/InjectorFactoryTests.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2022 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.guice; 18 | 19 | import com.google.inject.Guice; 20 | import org.junit.jupiter.api.BeforeEach; 21 | import org.junit.jupiter.api.Test; 22 | import org.mockito.Mockito; 23 | 24 | import org.springframework.context.ApplicationContextException; 25 | import org.springframework.context.annotation.AnnotationConfigApplicationContext; 26 | import org.springframework.context.annotation.Bean; 27 | import org.springframework.context.annotation.Configuration; 28 | import org.springframework.guice.annotation.EnableGuiceModules; 29 | import org.springframework.guice.annotation.InjectorFactory; 30 | 31 | import static org.assertj.core.api.Assertions.assertThatExceptionOfType; 32 | 33 | public class InjectorFactoryTests { 34 | 35 | private static final InjectorFactory injectorFactory = Mockito.mock(InjectorFactory.class); 36 | 37 | @BeforeEach 38 | public void init() { 39 | Mockito.when(injectorFactory.createInjector(Mockito.anyList())).thenReturn(Guice.createInjector()); 40 | } 41 | 42 | @Test 43 | public void testCustomInjectorIsCreated() { 44 | AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(InjectorFactoryConfig.class, 45 | ModulesConfig.class); 46 | Mockito.verify(injectorFactory, Mockito.times(1)).createInjector(Mockito.anyList()); 47 | context.close(); 48 | } 49 | 50 | @Test 51 | public void testMultipleInjectorFactoriesThrowsApplicationContextException() { 52 | assertThatExceptionOfType(ApplicationContextException.class).isThrownBy(() -> { 53 | AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext( 54 | InjectorFactoryConfig.class, SecondInjectorFactoryConfig.class, ModulesConfig.class); 55 | context.close(); 56 | }); 57 | } 58 | 59 | @Configuration 60 | @EnableGuiceModules 61 | static class ModulesConfig { 62 | 63 | } 64 | 65 | @Configuration 66 | static class InjectorFactoryConfig { 67 | 68 | @Bean 69 | InjectorFactory injectorFactory() { 70 | return injectorFactory; 71 | } 72 | 73 | } 74 | 75 | @Configuration 76 | static class SecondInjectorFactoryConfig { 77 | 78 | @Bean 79 | InjectorFactory injectorFactory2() { 80 | return injectorFactory; 81 | } 82 | 83 | } 84 | 85 | } 86 | -------------------------------------------------------------------------------- /src/test/java/org/springframework/guice/JustInTimeBindingTests.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019-2022 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.guice; 18 | 19 | import jakarta.inject.Inject; 20 | import org.junit.jupiter.api.AfterEach; 21 | import org.junit.jupiter.api.Test; 22 | 23 | import org.springframework.beans.factory.UnsatisfiedDependencyException; 24 | import org.springframework.beans.factory.support.RootBeanDefinition; 25 | import org.springframework.context.annotation.AnnotationConfigApplicationContext; 26 | import org.springframework.context.annotation.Configuration; 27 | import org.springframework.guice.annotation.EnableGuiceModules; 28 | 29 | import static org.assertj.core.api.Assertions.assertThat; 30 | import static org.assertj.core.api.Assertions.assertThatExceptionOfType; 31 | 32 | public class JustInTimeBindingTests { 33 | 34 | @AfterEach 35 | public void tearDown() { 36 | System.clearProperty("spring.guice.autowireJIT"); 37 | } 38 | 39 | @Test 40 | public void springWithJustInTimeBinding() { 41 | System.setProperty("spring.guice.autowireJIT", "true"); 42 | assertThat(springGetFoo()).isNotNull(); 43 | } 44 | 45 | @Test 46 | public void springWithoutJustInTimeBinding() { 47 | System.setProperty("spring.guice.autowireJIT", "false"); 48 | assertThatExceptionOfType(UnsatisfiedDependencyException.class).isThrownBy(this::springGetFoo); 49 | } 50 | 51 | @SuppressWarnings("resource") 52 | private Foo springGetFoo() { 53 | AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ModulesConfig.class); 54 | context.getDefaultListableBeanFactory().registerBeanDefinition(Foo.class.getSimpleName(), 55 | new RootBeanDefinition(Foo.class)); 56 | return context.getBean(Foo.class); 57 | } 58 | 59 | @Configuration 60 | @EnableGuiceModules 61 | static class ModulesConfig { 62 | 63 | } 64 | 65 | public static class Service { 66 | 67 | } 68 | 69 | public static class Foo { 70 | 71 | Service service; 72 | 73 | @Inject 74 | public Foo(Service service) { 75 | this.service = service; 76 | } 77 | 78 | } 79 | 80 | } 81 | -------------------------------------------------------------------------------- /src/test/java/org/springframework/guice/LazyInitializationTests.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2022 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.guice; 18 | 19 | import com.google.inject.AbstractModule; 20 | import org.junit.jupiter.api.Test; 21 | 22 | import org.springframework.aop.support.AopUtils; 23 | import org.springframework.context.annotation.AnnotationConfigApplicationContext; 24 | import org.springframework.context.annotation.Bean; 25 | import org.springframework.context.annotation.Configuration; 26 | import org.springframework.context.annotation.Lazy; 27 | import org.springframework.guice.annotation.EnableGuiceModules; 28 | 29 | import static org.assertj.core.api.Assertions.assertThat; 30 | 31 | public class LazyInitializationTests { 32 | 33 | @Test 34 | public void lazyAnnotationIsRespectedOnInjectionPointForGuiceBinding() { 35 | AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(); 36 | context.register(TestConfig.class); 37 | context.register(GuiceConfig.class); 38 | context.refresh(); 39 | 40 | Service service = context.getBean(Service.class); 41 | 42 | assertThat(AopUtils.isAopProxy(service.getBean())).isTrue(); 43 | assertThat(context.getBean(TestBean.class)).isNotNull(); 44 | } 45 | 46 | @Test 47 | public void lazyAnnotationIsRespectedOnInjectionPointForSpringBinding() { 48 | AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(); 49 | context.register(TestConfig.class); 50 | context.register(SpringConfig.class); 51 | context.refresh(); 52 | 53 | Service service = context.getBean(Service.class); 54 | 55 | assertThat(AopUtils.isAopProxy(service.getBean())).isTrue(); 56 | assertThat(context.getBean(TestBean.class)).isNotNull(); 57 | } 58 | 59 | @Configuration 60 | @EnableGuiceModules 61 | static class TestConfig { 62 | 63 | @Bean 64 | Service service(@Lazy TestBean bean) { 65 | return new Service(bean); 66 | } 67 | 68 | } 69 | 70 | @Configuration 71 | static class GuiceConfig { 72 | 73 | @Bean 74 | static GuiceModule guiceModule() { 75 | return new GuiceModule(); 76 | } 77 | 78 | } 79 | 80 | @Configuration 81 | static class SpringConfig { 82 | 83 | @Bean 84 | TestBean testBean() { 85 | return new TestBean(); 86 | } 87 | 88 | } 89 | 90 | static class GuiceModule extends AbstractModule { 91 | 92 | @Override 93 | protected void configure() { 94 | bind(TestBean.class).asEagerSingleton(); 95 | } 96 | 97 | } 98 | 99 | static class Service { 100 | 101 | private final TestBean bean; 102 | 103 | Service(TestBean bean) { 104 | this.bean = bean; 105 | } 106 | 107 | TestBean getBean() { 108 | return this.bean; 109 | } 110 | 111 | } 112 | 113 | static class TestBean { 114 | 115 | } 116 | 117 | } 118 | -------------------------------------------------------------------------------- /src/test/java/org/springframework/guice/MapBindingDeduplicationTests.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018-2022 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.guice; 18 | 19 | import java.util.Map; 20 | 21 | import com.google.inject.AbstractModule; 22 | import com.google.inject.Module; 23 | import com.google.inject.Provider; 24 | import com.google.inject.multibindings.MapBinder; 25 | import org.junit.jupiter.api.AfterAll; 26 | import org.junit.jupiter.api.Test; 27 | 28 | import org.springframework.context.annotation.AnnotationConfigApplicationContext; 29 | import org.springframework.context.annotation.Bean; 30 | import org.springframework.context.annotation.Configuration; 31 | import org.springframework.core.ResolvableType; 32 | import org.springframework.guice.annotation.EnableGuiceModules; 33 | import org.springframework.guice.module.SpringModule; 34 | 35 | import static org.assertj.core.api.Assertions.assertThat; 36 | 37 | public class MapBindingDeduplicationTests { 38 | 39 | @AfterAll 40 | public static void cleanUp() { 41 | System.clearProperty("spring.guice.dedup"); 42 | } 43 | 44 | @Test 45 | public void mapBindingGuiceOnly() { 46 | System.setProperty("spring.guice.dedup", "false"); 47 | AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext( 48 | MapBindingGuiceOnlyTestsConfig.class); 49 | 50 | String[] beanNamesForType = context 51 | .getBeanNamesForType(ResolvableType.forClassWithGenerics(Map.class, String.class, Provider.class)); 52 | @SuppressWarnings("unchecked") 53 | Map> dependencyProvider = (Map>) context 54 | .getBean(beanNamesForType[0]); 55 | 56 | assertThat(dependencyProvider.size()).isEqualTo(2); 57 | assertThat(dependencyProvider.get("someQualifier").get()).isInstanceOf(SomeDependency.class); 58 | 59 | context.close(); 60 | } 61 | 62 | @Test 63 | public void mapBindingConflictingConcreteClass() { 64 | System.setProperty("spring.guice.dedup", "true"); 65 | AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext( 66 | MapBindingConcreteClassTestsConfig.class); 67 | 68 | String[] beanNamesForType = context 69 | .getBeanNamesForType(ResolvableType.forClassWithGenerics(Map.class, String.class, Provider.class)); 70 | @SuppressWarnings("unchecked") 71 | Map> dependencyProvider = (Map>) context 72 | .getBean(beanNamesForType[0]); 73 | 74 | assertThat(dependencyProvider.size()).isEqualTo(2); 75 | assertThat(dependencyProvider.get("someQualifier").get()).isInstanceOf(SomeDependency.class); 76 | 77 | SomeDependency someDependency = context.getBean(SomeDependency.class); 78 | assertThat(someDependency.getSource()).isEqualTo(SpringModule.SPRING_GUICE_SOURCE); 79 | 80 | context.close(); 81 | } 82 | 83 | interface Dependency { 84 | 85 | } 86 | 87 | public static class SomeDependency implements Dependency { 88 | 89 | private String source = "guice"; 90 | 91 | public void setSource(String source) { 92 | this.source = source; 93 | } 94 | 95 | public String getSource() { 96 | return this.source; 97 | } 98 | 99 | } 100 | 101 | public static class SomeOptionalDependency implements Dependency { 102 | 103 | } 104 | 105 | @EnableGuiceModules 106 | @Configuration 107 | static class MapBindingGuiceOnlyTestsConfig { 108 | 109 | @Bean 110 | static Module module() { 111 | return new AbstractModule() { 112 | @Override 113 | protected void configure() { 114 | MapBinder bindings = MapBinder.newMapBinder(binder(), String.class, 115 | Dependency.class); 116 | bindings.addBinding("someQualifier").to(SomeDependency.class); 117 | bindings.addBinding("someOtherQualifier").to(SomeOptionalDependency.class); 118 | } 119 | }; 120 | } 121 | 122 | } 123 | 124 | @EnableGuiceModules 125 | @Configuration 126 | static class MapBindingConcreteClassTestsConfig { 127 | 128 | @Bean 129 | SomeDependency dependency() { 130 | SomeDependency someDependency = new SomeDependency(); 131 | someDependency.setSource(SpringModule.SPRING_GUICE_SOURCE); 132 | return someDependency; 133 | } 134 | 135 | @Bean 136 | static Module module() { 137 | return new AbstractModule() { 138 | @Override 139 | protected void configure() { 140 | MapBinder bindings = MapBinder.newMapBinder(binder(), String.class, 141 | Dependency.class); 142 | bindings.addBinding("someQualifier").to(SomeDependency.class); 143 | // Intentionally duplicate the binding to ensure that every key is 144 | // available after deduplication 145 | bindings.addBinding("someQualifier").to(SomeDependency.class); 146 | bindings.addBinding("someOtherQualifier").to(SomeOptionalDependency.class); 147 | } 148 | }; 149 | } 150 | 151 | } 152 | 153 | } 154 | -------------------------------------------------------------------------------- /src/test/java/org/springframework/guice/MapWiringTests.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019-2022 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.guice; 18 | 19 | import java.util.Map; 20 | 21 | import com.google.inject.AbstractModule; 22 | import org.junit.jupiter.api.Test; 23 | 24 | import org.springframework.context.annotation.AnnotationConfigApplicationContext; 25 | import org.springframework.context.annotation.Bean; 26 | import org.springframework.context.annotation.Configuration; 27 | import org.springframework.guice.annotation.EnableGuiceModules; 28 | 29 | import static org.assertj.core.api.Assertions.assertThat; 30 | 31 | /** 32 | * Test injecting Map 33 | * 34 | * @author Dave Syer 35 | */ 36 | public class MapWiringTests { 37 | 38 | // Test Guice -> Spring direction 39 | @SuppressWarnings({ "resource", "unused" }) 40 | @Test 41 | public void testProvidesMap() { 42 | AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ModulesConfig.class, 43 | FooBar.class); 44 | Bar bar = context.getBean(Bar.class); 45 | } 46 | 47 | @Configuration 48 | @EnableGuiceModules 49 | static class ModulesConfig { 50 | 51 | @Bean 52 | static TestConfig testConfig() { 53 | return new TestConfig(); 54 | } 55 | 56 | } 57 | 58 | @Configuration 59 | static class FooBar { 60 | 61 | @Bean 62 | Bar foo(Map foos) { 63 | assertThat(foos.isEmpty()).isFalse(); 64 | return new Bar(); 65 | } 66 | 67 | } 68 | 69 | static class TestConfig extends AbstractModule { 70 | 71 | @Override 72 | protected void configure() { 73 | bind(Foo.class); 74 | } 75 | 76 | } 77 | 78 | static class Foo { 79 | 80 | } 81 | 82 | static class Bar { 83 | 84 | } 85 | 86 | } 87 | -------------------------------------------------------------------------------- /src/test/java/org/springframework/guice/ModuleFilteringTests.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019-2022 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.guice; 18 | 19 | import com.google.inject.AbstractModule; 20 | import com.google.inject.Guice; 21 | import com.google.inject.Module; 22 | import com.google.inject.Stage; 23 | import org.junit.jupiter.api.AfterAll; 24 | import org.junit.jupiter.api.Test; 25 | 26 | import org.springframework.beans.factory.NoSuchBeanDefinitionException; 27 | import org.springframework.context.annotation.AnnotationConfigApplicationContext; 28 | import org.springframework.context.annotation.Bean; 29 | import org.springframework.context.annotation.Configuration; 30 | import org.springframework.guice.annotation.EnableGuiceModules; 31 | import org.springframework.guice.annotation.InjectorFactory; 32 | 33 | import static org.assertj.core.api.Assertions.assertThat; 34 | import static org.assertj.core.api.Assertions.assertThatExceptionOfType; 35 | 36 | public class ModuleFilteringTests { 37 | 38 | @AfterAll 39 | public static void cleanUp() { 40 | System.clearProperty("spring.guice.modules.exclude"); 41 | } 42 | 43 | @Test 44 | public void verifyAllIsWellWhenNoModulesFiltered() { 45 | System.setProperty("spring.guice.modules.exclude", "FilterSomeNonExistentModule"); 46 | assertThatExceptionOfType(RuntimeException.class).isThrownBy(() -> { 47 | AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext( 48 | ModuleFilteringTestsConfig.class); 49 | SomeInterface someDependency = context.getBean(SomeInterface.class); 50 | assertThat(someDependency).isNotNull(); 51 | context.close(); 52 | }); 53 | } 54 | 55 | @Test 56 | public void verifyFilteredModuleIsFiltered() { 57 | System.setProperty("spring.guice.modules.exclude", "FilterThisModule"); 58 | try (AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext( 59 | ModuleFilteringTestsConfig.class)) { 60 | assertThatExceptionOfType(NoSuchBeanDefinitionException.class) 61 | .isThrownBy(() -> context.getBean(SomeInterface.class)); 62 | } 63 | } 64 | 65 | public interface SomeInterface { 66 | 67 | } 68 | 69 | public static class SomeDependency implements SomeInterface { 70 | 71 | public SomeDependency() { 72 | throw new RuntimeException("Should never be instantiated"); 73 | } 74 | 75 | } 76 | 77 | public static class FilterThisModule extends AbstractModule { 78 | 79 | @Override 80 | protected void configure() { 81 | bind(SomeInterface.class).to(SomeDependency.class).asEagerSingleton(); 82 | } 83 | 84 | } 85 | 86 | @EnableGuiceModules 87 | @Configuration 88 | static class ModuleFilteringTestsConfig { 89 | 90 | @Bean 91 | InjectorFactory injectorFactory() { 92 | return (modules) -> Guice.createInjector(Stage.PRODUCTION, modules); 93 | } 94 | 95 | @Bean 96 | static Module module() { 97 | return new AbstractModule() { 98 | 99 | @Override 100 | protected void configure() { 101 | install(new FilterThisModule()); 102 | } 103 | }; 104 | } 105 | 106 | } 107 | 108 | } 109 | -------------------------------------------------------------------------------- /src/test/java/org/springframework/guice/NativeGuiceTests.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2022 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.guice; 18 | 19 | import com.google.inject.AbstractModule; 20 | import com.google.inject.Guice; 21 | import com.google.inject.Injector; 22 | import com.google.inject.name.Names; 23 | import jakarta.inject.Inject; 24 | import org.junit.jupiter.api.Test; 25 | 26 | import static org.assertj.core.api.Assertions.assertThat; 27 | 28 | /** 29 | * @author Dave Syer 30 | * 31 | */ 32 | public class NativeGuiceTests { 33 | 34 | @Inject 35 | private Foo bar; 36 | 37 | @Test 38 | public void test() { 39 | Injector app = Guice.createInjector(new TestConfig()); 40 | NativeGuiceTests instance = app.getInstance(NativeGuiceTests.class); 41 | assertThat(instance.bar).isNotNull(); 42 | } 43 | 44 | public static class TestConfig extends AbstractModule { 45 | 46 | @Override 47 | protected void configure() { 48 | bind(Foo.class).annotatedWith(Names.named("bar")).to(Foo.class); 49 | } 50 | 51 | } 52 | 53 | public static class Foo { 54 | 55 | } 56 | 57 | } 58 | -------------------------------------------------------------------------------- /src/test/java/org/springframework/guice/PartialInjectionTests.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2013-2014 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.guice; 18 | 19 | import com.google.inject.AbstractModule; 20 | import com.google.inject.Guice; 21 | import com.google.inject.Injector; 22 | import com.google.inject.Provides; 23 | import jakarta.inject.Named; 24 | import jakarta.inject.Singleton; 25 | import org.junit.jupiter.api.Test; 26 | 27 | import org.springframework.beans.factory.annotation.Autowired; 28 | import org.springframework.beans.factory.annotation.Qualifier; 29 | import org.springframework.guice.module.BeanFactoryProvider; 30 | import org.springframework.guice.module.SpringModule; 31 | import org.springframework.stereotype.Component; 32 | 33 | import static org.assertj.core.api.Assertions.assertThat; 34 | 35 | public class PartialInjectionTests { 36 | 37 | @Test 38 | void shouldResolveNamedComponentsInSpringWhenUsingSetterInjection() { 39 | Injector injector = guiceInjectorWithSpringBean(SetterInjectionExample.class); 40 | 41 | SetterInjectionExample example = injector.getInstance(SetterInjectionExample.class); 42 | 43 | assertThat(example.getNamedMessage()).isEqualTo("banana"); 44 | } 45 | 46 | @Test 47 | void shouldResolveNamedComponentsInSpringWhenUsingConstructorInjection() { 48 | Injector injector = guiceInjectorWithSpringBean(ConstructorInjectionExample.class); 49 | 50 | ConstructorInjectionExample example = injector.getInstance(ConstructorInjectionExample.class); 51 | 52 | assertThat(example.getNamedMessage()).isEqualTo("banana"); 53 | } 54 | 55 | @Test 56 | void shouldResolveComponentsInSpringWhenUsingSetterInjection() { 57 | Injector injector = guiceInjectorWithSpringBean(SetterInjectionExample.class); 58 | 59 | SetterInjectionExample example = injector.getInstance(SetterInjectionExample.class); 60 | 61 | assertThat(example.getUnnamedMessage()).isEqualTo("apple"); 62 | } 63 | 64 | @Test 65 | void shouldResolveComponentsInSpringWhenUsingConstructorInjection() { 66 | Injector injector = guiceInjectorWithSpringBean(ConstructorInjectionExample.class); 67 | 68 | ConstructorInjectionExample example = injector.getInstance(ConstructorInjectionExample.class); 69 | 70 | assertThat(example.getUnnamedMessage()).isEqualTo("apple"); 71 | } 72 | 73 | @Test 74 | void shouldResolveNamedComponentOnSecondInjectWhenUsingConstructorInjection() { 75 | Injector injector = guiceInjectorWithSpringBean(ConstructorInjectionExample.class); 76 | 77 | ConstructorInjectionExample example = injector.getInstance(ConstructorInjectionExample.class); 78 | 79 | example.getNamedMessage(); 80 | assertThat(example.getNamedMessage()).isEqualTo("banana"); 81 | } 82 | 83 | @Test 84 | void shouldResolveNamedComponentOnSecondInjectWhenUsingSetterInjection() { 85 | Injector injector = guiceInjectorWithSpringBean(SetterInjectionExample.class); 86 | 87 | SetterInjectionExample example = injector.getInstance(SetterInjectionExample.class); 88 | 89 | example.getNamedMessage(); 90 | assertThat(example.getNamedMessage()).isEqualTo("banana"); 91 | } 92 | 93 | private Injector guiceInjectorWithSpringBean(Class classForContext) { 94 | Class[] components = new Class[] { classForContext }; 95 | BeanFactoryProvider beanFactoryProvider = BeanFactoryProvider.from(components); 96 | return Guice.createInjector(new SpringModule(beanFactoryProvider), new ExampleGuiceModule()); 97 | } 98 | 99 | @Component 100 | public static class SetterInjectionExample { 101 | 102 | @Autowired 103 | @Qualifier("named") 104 | private Dependency named; 105 | 106 | @Autowired 107 | private Dependency unnamed; 108 | 109 | public String getNamedMessage() { 110 | return this.named.getMessage(); 111 | } 112 | 113 | public String getUnnamedMessage() { 114 | return this.unnamed.getMessage(); 115 | } 116 | 117 | } 118 | 119 | @Component 120 | public static class ConstructorInjectionExample { 121 | 122 | private final Dependency named; 123 | 124 | private final Dependency unnamed; 125 | 126 | @Autowired 127 | public ConstructorInjectionExample(@Qualifier("named") Dependency named, Dependency unnamed) { 128 | this.named = named; 129 | this.unnamed = unnamed; 130 | } 131 | 132 | public String getNamedMessage() { 133 | return this.named.getMessage(); 134 | } 135 | 136 | public String getUnnamedMessage() { 137 | return this.unnamed.getMessage(); 138 | } 139 | 140 | } 141 | 142 | public static class ExampleGuiceModule extends AbstractModule { 143 | 144 | @Provides 145 | @Singleton 146 | @Named("named") 147 | public Dependency namedDependencyProvider() { 148 | return new Dependency("banana"); 149 | } 150 | 151 | @Provides 152 | @Singleton 153 | public Dependency unnamedDependencyProvider() { 154 | return new Dependency("apple"); 155 | } 156 | 157 | } 158 | 159 | public static class Dependency { 160 | 161 | private final String message; 162 | 163 | public Dependency(String message) { 164 | this.message = message; 165 | } 166 | 167 | public String getMessage() { 168 | return this.message; 169 | } 170 | 171 | } 172 | 173 | } 174 | -------------------------------------------------------------------------------- /src/test/java/org/springframework/guice/PrivateModuleTests.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018-2022 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.guice; 18 | 19 | import com.google.inject.AbstractModule; 20 | import com.google.inject.ConfigurationException; 21 | import com.google.inject.Injector; 22 | import com.google.inject.Key; 23 | import com.google.inject.Module; 24 | import com.google.inject.PrivateModule; 25 | import com.google.inject.name.Names; 26 | import org.junit.jupiter.api.AfterAll; 27 | import org.junit.jupiter.api.BeforeAll; 28 | import org.junit.jupiter.api.Test; 29 | 30 | import org.springframework.beans.factory.NoSuchBeanDefinitionException; 31 | import org.springframework.beans.factory.annotation.BeanFactoryAnnotationUtils; 32 | import org.springframework.context.annotation.AnnotationConfigApplicationContext; 33 | import org.springframework.context.annotation.Bean; 34 | import org.springframework.context.annotation.Configuration; 35 | import org.springframework.guice.annotation.EnableGuiceModules; 36 | 37 | import static org.assertj.core.api.Assertions.assertThat; 38 | import static org.assertj.core.api.Assertions.assertThatExceptionOfType; 39 | 40 | public class PrivateModuleTests { 41 | 42 | private static AnnotationConfigApplicationContext context; 43 | 44 | @BeforeAll 45 | public static void init() { 46 | context = new AnnotationConfigApplicationContext(PrivateModuleTestConfig.class); 47 | } 48 | 49 | @AfterAll 50 | public static void cleanup() { 51 | if (context != null) { 52 | context.close(); 53 | } 54 | } 55 | 56 | @Test 57 | public void verifyPrivateModulesCanExposeBindings() { 58 | Injector injector = context.getBean(Injector.class); 59 | SomeInterface injectorProvidedPrivateBinding = injector 60 | .getInstance(Key.get(SomeInterface.class, Names.named("exposed"))); 61 | assertThat(injectorProvidedPrivateBinding).isNotNull(); 62 | SomeInterface springProvidedPrivateBinding = context.getBean(SomeInterface.class); 63 | assertThat(springProvidedPrivateBinding).isNotNull(); 64 | SomeInterface namedPrivateBinding = BeanFactoryAnnotationUtils.qualifiedBeanOfType(context.getBeanFactory(), 65 | SomeInterface.class, "exposed"); 66 | assertThat(namedPrivateBinding).isNotNull(); 67 | assertThat(springProvidedPrivateBinding).isEqualTo(injectorProvidedPrivateBinding); 68 | assertThat(namedPrivateBinding).isEqualTo(injectorProvidedPrivateBinding); 69 | String beanDependingOnPrivateBinding = context.getBean("somethingThatWantsAPrivateBinding", String.class); 70 | assertThat(beanDependingOnPrivateBinding).isNotNull(); 71 | assertThat(beanDependingOnPrivateBinding).isEqualTo("foo"); 72 | } 73 | 74 | @Test 75 | public void verifyPrivateModulesPrivateBindingsAreNotExposedViaInjector() { 76 | Injector injector = context.getBean(Injector.class); 77 | assertThatExceptionOfType(ConfigurationException.class) 78 | .isThrownBy(() -> injector.getInstance(Key.get(SomeInterface.class, Names.named("notexposed")))); 79 | } 80 | 81 | @Test 82 | public void verifyPrivateModulesPrivateBindingsAreNotExposedViaSpring() { 83 | assertThatExceptionOfType(NoSuchBeanDefinitionException.class) 84 | .isThrownBy(() -> context.getBean("notexposed", SomeInterface.class)); 85 | } 86 | 87 | @Test 88 | public void verifyPrivateModulesPrivateBindingsAreNotExposedViaSpringWithQualifier() { 89 | assertThatExceptionOfType(NoSuchBeanDefinitionException.class).isThrownBy(() -> BeanFactoryAnnotationUtils 90 | .qualifiedBeanOfType(context.getBeanFactory(), SomeInterface.class, "notexposed")); 91 | } 92 | 93 | public interface SomeInterface { 94 | 95 | } 96 | 97 | public static class SomePrivateBinding implements SomeInterface { 98 | 99 | } 100 | 101 | public static class SomePrivateModule extends PrivateModule { 102 | 103 | @Override 104 | protected void configure() { 105 | bind(SomeInterface.class).annotatedWith(Names.named("exposed")).to(SomePrivateBinding.class) 106 | .asEagerSingleton(); 107 | bind(SomeInterface.class).annotatedWith(Names.named("notexposed")).to(SomePrivateBinding.class) 108 | .asEagerSingleton(); 109 | expose(SomeInterface.class).annotatedWith(Names.named("exposed")); 110 | } 111 | 112 | } 113 | 114 | @EnableGuiceModules 115 | @Configuration 116 | static class PrivateModuleTestConfig { 117 | 118 | @Bean 119 | String somethingThatWantsAPrivateBinding(SomeInterface privateBinding) { 120 | return "foo"; 121 | } 122 | 123 | @Bean 124 | static Module module() { 125 | return new AbstractModule() { 126 | @Override 127 | protected void configure() { 128 | install(new SomePrivateModule()); 129 | } 130 | }; 131 | } 132 | 133 | } 134 | 135 | } 136 | -------------------------------------------------------------------------------- /src/test/java/org/springframework/guice/PrototypeScopedBeanTests.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2022 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.guice; 18 | 19 | import com.google.inject.AbstractModule; 20 | import com.google.inject.Injector; 21 | import com.google.inject.Module; 22 | import jakarta.inject.Inject; 23 | import org.junit.jupiter.api.Test; 24 | 25 | import org.springframework.context.annotation.AnnotationConfigApplicationContext; 26 | import org.springframework.context.annotation.Bean; 27 | import org.springframework.context.annotation.Configuration; 28 | import org.springframework.context.annotation.Scope; 29 | import org.springframework.guice.annotation.EnableGuiceModules; 30 | 31 | import static org.assertj.core.api.Assertions.assertThat; 32 | 33 | public class PrototypeScopedBeanTests { 34 | 35 | @Test 36 | public void testPrototypeScopedBeans() { 37 | AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ModulesConfig.class); 38 | Injector injector = context.getBean(Injector.class); 39 | GuiceService1 gs1 = injector.getInstance(GuiceService1.class); 40 | GuiceService2 gs2 = injector.getInstance((GuiceService2.class)); 41 | assertThat(gs1).isNotNull(); 42 | assertThat(gs2).isNotNull(); 43 | assertThat(gs2.bean).isNotEqualTo(gs1.bean); 44 | } 45 | 46 | @Configuration 47 | @EnableGuiceModules 48 | static class ModulesConfig { 49 | 50 | @Bean 51 | static Module guiceModule() { 52 | return new AbstractModule() { 53 | @Override 54 | protected void configure() { 55 | bind(GuiceService1.class).asEagerSingleton(); 56 | bind(GuiceService2.class).asEagerSingleton(); 57 | } 58 | }; 59 | } 60 | 61 | @Bean 62 | @Scope("prototype") 63 | PrototypeBean prototypeBean() { 64 | return new PrototypeBean(); 65 | } 66 | 67 | } 68 | 69 | public static class PrototypeBean { 70 | 71 | } 72 | 73 | public static class GuiceService1 { 74 | 75 | @Inject 76 | PrototypeBean bean; 77 | 78 | } 79 | 80 | public static class GuiceService2 { 81 | 82 | @Inject 83 | PrototypeBean bean; 84 | 85 | } 86 | 87 | } 88 | -------------------------------------------------------------------------------- /src/test/java/org/springframework/guice/ProvidesSupplierWiringTests.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018-2022 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.guice; 18 | 19 | import java.util.function.Supplier; 20 | 21 | import com.google.inject.AbstractModule; 22 | import com.google.inject.Key; 23 | import com.google.inject.Provides; 24 | import com.google.inject.TypeLiteral; 25 | import jakarta.inject.Singleton; 26 | import org.junit.jupiter.api.Disabled; 27 | import org.junit.jupiter.api.Test; 28 | 29 | import org.springframework.context.annotation.AnnotationConfigApplicationContext; 30 | import org.springframework.context.annotation.Bean; 31 | import org.springframework.context.annotation.Configuration; 32 | import org.springframework.guice.annotation.EnableGuiceModules; 33 | import org.springframework.guice.injector.SpringInjector; 34 | 35 | /** 36 | * Test Generics (e.g., {@literal Supplier}) not losing type info across bridge in both 37 | * directions 38 | * 39 | * @author Howard Yuan 40 | */ 41 | public class ProvidesSupplierWiringTests { 42 | 43 | // Test Guice -> Spring direction 44 | @SuppressWarnings({ "resource", "unused" }) 45 | @Test 46 | public void testProvidesSupplier() { 47 | AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ModulesConfig.class, 48 | FooBar.class); 49 | Foo foo = context.getBean(Foo.class); 50 | Bar bar = context.getBean(Bar.class); 51 | } 52 | 53 | // Test Spring -> Guice direction 54 | // ToDo -- Today this direction doesn't work without further work. Ignore the test for 55 | // now. 56 | @SuppressWarnings("unused") 57 | @Disabled 58 | @Test 59 | public void testProvidesSupplierSpring() { 60 | AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(FooBarSpring.class); 61 | SpringInjector injector = new SpringInjector(context); 62 | Foo_Spring fooSpring = injector.getInstance(Key.get(new TypeLiteral>() { 63 | })).get(); 64 | Bar_Spring barSpring = injector.getInstance(Key.get(new TypeLiteral>() { 65 | })).get(); 66 | } 67 | 68 | @Configuration 69 | @EnableGuiceModules 70 | static class ModulesConfig { 71 | 72 | @Bean 73 | static TestConfig testConfig() { 74 | return new TestConfig(); 75 | } 76 | 77 | } 78 | 79 | @Configuration 80 | static class FooBar { 81 | 82 | @Bean 83 | Foo foo(Supplier supplier) { 84 | return supplier.get(); 85 | } 86 | 87 | @Bean 88 | Bar bar(Supplier supplier) { 89 | return supplier.get(); 90 | } 91 | 92 | } 93 | 94 | static class TestConfig extends AbstractModule { 95 | 96 | @Override 97 | protected void configure() { 98 | } 99 | 100 | @Singleton 101 | @Provides 102 | Supplier getFoo() { 103 | return () -> new Foo(); 104 | } 105 | 106 | @Singleton 107 | @Provides 108 | Supplier getBar() { 109 | return () -> new Bar(); 110 | } 111 | 112 | } 113 | 114 | static class Foo { 115 | 116 | } 117 | 118 | static class Bar { 119 | 120 | } 121 | 122 | @Configuration 123 | static class FooBarSpring { 124 | 125 | @Bean 126 | Supplier fooSpring() { 127 | return () -> new Foo_Spring(); 128 | } 129 | 130 | @Bean 131 | Bar_Spring barSpring() { 132 | return new Bar_Spring(); 133 | } 134 | 135 | } 136 | 137 | static class Foo_Spring { 138 | 139 | } 140 | 141 | static class Bar_Spring { 142 | 143 | } 144 | 145 | } 146 | -------------------------------------------------------------------------------- /src/test/java/org/springframework/guice/ScopingTests.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019-2022 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.guice; 18 | 19 | import com.google.inject.AbstractModule; 20 | import com.google.inject.Key; 21 | import com.google.inject.Module; 22 | import com.google.inject.Provider; 23 | import com.google.inject.Scope; 24 | import org.junit.jupiter.api.Test; 25 | 26 | import org.springframework.context.annotation.AnnotationConfigApplicationContext; 27 | import org.springframework.context.annotation.Bean; 28 | import org.springframework.context.annotation.Configuration; 29 | import org.springframework.guice.annotation.EnableGuiceModules; 30 | 31 | import static org.assertj.core.api.Assertions.assertThat; 32 | 33 | public class ScopingTests { 34 | 35 | @Test 36 | public void verifyScopes() { 37 | AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ScopingTestsConfig.class); 38 | SomeSingletonDependency someSingletonDependency1 = context.getBean(SomeSingletonDependency.class); 39 | SomeSingletonDependency someSingletonDependency2 = context.getBean(SomeSingletonDependency.class); 40 | 41 | assertThat(someSingletonDependency1).isNotNull(); 42 | assertThat(someSingletonDependency2).isNotNull(); 43 | assertThat(someSingletonDependency2).isEqualTo(someSingletonDependency1); 44 | 45 | SomeNoScopeDependency someNoScopeDependency1 = context.getBean(SomeNoScopeDependency.class); 46 | SomeNoScopeDependency someNoScopeDependency2 = context.getBean(SomeNoScopeDependency.class); 47 | 48 | assertThat(someNoScopeDependency1).isNotNull(); 49 | assertThat(someNoScopeDependency2).isNotNull(); 50 | assertThat(someNoScopeDependency2).isNotEqualTo(someNoScopeDependency1); 51 | 52 | SomeCustomScopeDependency someCustomScopeDependency1 = context.getBean(SomeCustomScopeDependency.class); 53 | SomeCustomScopeDependency someCustomScopeDependency2 = context.getBean(SomeCustomScopeDependency.class); 54 | 55 | assertThat(someCustomScopeDependency1).isNotNull(); 56 | assertThat(someCustomScopeDependency2).isNotNull(); 57 | assertThat(someCustomScopeDependency2).isNotEqualTo(someCustomScopeDependency1); 58 | assertThat("custom").isEqualTo(someCustomScopeDependency1.value); 59 | assertThat("custom").isEqualTo(someCustomScopeDependency2.value); 60 | 61 | context.close(); 62 | } 63 | 64 | public static class SomeSingletonDependency { 65 | 66 | } 67 | 68 | public static class SomeNoScopeDependency { 69 | 70 | } 71 | 72 | public static class SomeCustomScopeDependency { 73 | 74 | String value; 75 | 76 | public SomeCustomScopeDependency() { 77 | } 78 | 79 | public SomeCustomScopeDependency(String value) { 80 | this.value = value; 81 | } 82 | 83 | } 84 | 85 | public interface CustomScope extends Scope { 86 | 87 | } 88 | 89 | @EnableGuiceModules 90 | @Configuration 91 | static class ScopingTestsConfig { 92 | 93 | @Bean 94 | static Module module() { 95 | return new AbstractModule() { 96 | @Override 97 | protected void configure() { 98 | CustomScope customScope = new CustomScope() { 99 | @SuppressWarnings("unchecked") 100 | @Override 101 | public Provider scope(Key key, Provider unscoped) { 102 | Provider provider = () -> new SomeCustomScopeDependency("custom"); 103 | return (Provider) provider; 104 | } 105 | }; 106 | bind(SomeSingletonDependency.class).asEagerSingleton(); 107 | bind(SomeNoScopeDependency.class); 108 | bind(SomeCustomScopeDependency.class).in(customScope); 109 | } 110 | }; 111 | } 112 | 113 | } 114 | 115 | } 116 | -------------------------------------------------------------------------------- /src/test/java/org/springframework/guice/SetBindingTests.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.guice; 18 | 19 | import com.google.inject.AbstractModule; 20 | import com.google.inject.Guice; 21 | import com.google.inject.Injector; 22 | import com.google.inject.Module; 23 | import com.google.inject.multibindings.Multibinder; 24 | import jakarta.inject.Inject; 25 | import org.junit.jupiter.api.Test; 26 | 27 | import org.springframework.beans.factory.annotation.Autowired; 28 | import org.springframework.context.annotation.AnnotationConfigApplicationContext; 29 | import org.springframework.context.annotation.Bean; 30 | import org.springframework.context.annotation.Configuration; 31 | import org.springframework.guice.annotation.EnableGuiceModules; 32 | 33 | import static org.assertj.core.api.Assertions.assertThat; 34 | 35 | public class SetBindingTests { 36 | 37 | @Inject 38 | private Benz bar; 39 | 40 | @Test 41 | public void testNativeGuiceBinding() { 42 | Injector app = Guice.createInjector(new AutomobileModule()); 43 | SetBindingTests instance = app.getInstance(SetBindingTests.class); 44 | assertThat(instance.bar).isNotNull(); 45 | } 46 | 47 | @Test 48 | void testSpringBinding() { 49 | AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(); 50 | context.register(SpringGuiceConfig.class); 51 | context.refresh(); 52 | Benz car = context.getBean(SpringGuiceConfig.class).getBenz(); 53 | assertThat(car).isNotNull(); 54 | assertThat(car.getModel()).contains("220"); 55 | context.close(); 56 | } 57 | 58 | @Configuration 59 | @EnableGuiceModules 60 | public static class SpringGuiceConfig { 61 | 62 | @Autowired 63 | private Benz benz; 64 | 65 | public Benz getBenz() { 66 | return this.benz; 67 | } 68 | 69 | @Bean 70 | public static Module module() { 71 | return new AutomobileModule(); 72 | } 73 | 74 | } 75 | 76 | interface Car { 77 | 78 | String getModel(); 79 | 80 | } 81 | 82 | static class Audi implements Car { 83 | 84 | @Override 85 | public String getModel() { 86 | return "Audi A4"; 87 | } 88 | 89 | } 90 | 91 | static class Benz implements Car { 92 | 93 | @Override 94 | public String getModel() { 95 | return "C 220"; 96 | } 97 | 98 | } 99 | 100 | static class AutomobileModule extends AbstractModule { 101 | 102 | @Override 103 | protected void configure() { 104 | Multibinder uriBinder = Multibinder.newSetBinder(binder(), Car.class); 105 | uriBinder.addBinding().to(Audi.class); 106 | uriBinder.addBinding().to(Benz.class); 107 | } 108 | 109 | } 110 | 111 | } 112 | -------------------------------------------------------------------------------- /src/test/java/org/springframework/guice/SimpleWiringTests.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014-2022 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.guice; 18 | 19 | import com.google.inject.AbstractModule; 20 | import com.google.inject.Guice; 21 | import com.google.inject.Injector; 22 | import jakarta.inject.Inject; 23 | import org.junit.jupiter.api.Test; 24 | 25 | import org.springframework.beans.factory.support.RootBeanDefinition; 26 | import org.springframework.context.annotation.AnnotationConfigApplicationContext; 27 | import org.springframework.context.annotation.Configuration; 28 | import org.springframework.guice.annotation.EnableGuiceModules; 29 | import org.springframework.guice.injector.SpringInjector; 30 | 31 | import static org.assertj.core.api.Assertions.assertThat; 32 | 33 | public class SimpleWiringTests { 34 | 35 | @Test 36 | public void guiceyFoo() { 37 | Injector app = Guice.createInjector(new TestConfig()); 38 | assertThat(app.getInstance(Foo.class)).isNotNull(); 39 | } 40 | 41 | @Test 42 | public void springyFoo() { 43 | @SuppressWarnings("resource") 44 | AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(TestConfig.class, 45 | MyService.class); 46 | context.getDefaultListableBeanFactory().registerBeanDefinition(Foo.class.getSimpleName(), 47 | new RootBeanDefinition(Foo.class)); 48 | assertThat(context.getBean(Foo.class)).isNotNull(); 49 | } 50 | 51 | @Test 52 | public void hybridFoo() { 53 | AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(TestConfig.class, 54 | ModulesConfig.class); 55 | Injector app = new SpringInjector(context); 56 | assertThat(app.getInstance(Foo.class)).isNotNull(); 57 | } 58 | 59 | @Configuration 60 | @EnableGuiceModules 61 | static class ModulesConfig { 62 | 63 | } 64 | 65 | public static class TestConfig extends AbstractModule { 66 | 67 | @Override 68 | protected void configure() { 69 | bind(Service.class).to(MyService.class); 70 | } 71 | 72 | } 73 | 74 | interface Service { 75 | 76 | } 77 | 78 | public static class MyService implements Service { 79 | 80 | } 81 | 82 | public static class Foo { 83 | 84 | @Inject 85 | public Foo(Service service) { 86 | } 87 | 88 | } 89 | 90 | } 91 | -------------------------------------------------------------------------------- /src/test/java/org/springframework/guice/SpringAutowiredCollectionTests.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019-2022 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.guice; 18 | 19 | import java.util.Map; 20 | 21 | import com.google.inject.AbstractModule; 22 | import com.google.inject.Injector; 23 | import org.junit.jupiter.api.Test; 24 | 25 | import org.springframework.context.annotation.AnnotationConfigApplicationContext; 26 | import org.springframework.context.annotation.Bean; 27 | import org.springframework.context.annotation.Configuration; 28 | import org.springframework.guice.annotation.EnableGuiceModules; 29 | import org.springframework.guice.injector.SpringInjector; 30 | 31 | import static org.assertj.core.api.Assertions.assertThat; 32 | 33 | public class SpringAutowiredCollectionTests { 34 | 35 | @Test 36 | public void getAutowiredCollection() { 37 | AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(); 38 | context.register(TestConfig.class); 39 | context.refresh(); 40 | Injector injector = new SpringInjector(context); 41 | 42 | ServicesHolder servicesHolder = injector.getInstance(ServicesHolder.class); 43 | 44 | assertThat(servicesHolder.existingServices).hasSize(2); 45 | assertThat(servicesHolder.nonExistingServices).isEmpty(); 46 | } 47 | 48 | @Configuration 49 | @EnableGuiceModules 50 | static class TestConfig { 51 | 52 | @Bean 53 | ServicesHolder serviceHolder(Map existingServices, 54 | Map nonExistingServices) { 55 | return new ServicesHolder(existingServices, nonExistingServices); 56 | } 57 | 58 | @Bean 59 | Service service() { 60 | return new Service(); 61 | } 62 | 63 | @Bean 64 | static GuiceModule guiceServiceModule() { 65 | return new GuiceModule(); 66 | } 67 | 68 | } 69 | 70 | static class Service { 71 | 72 | } 73 | 74 | static class NonExistingService { 75 | 76 | } 77 | 78 | static class GuiceModule extends AbstractModule { 79 | 80 | @Override 81 | protected void configure() { 82 | bind(Service.class).asEagerSingleton(); 83 | } 84 | 85 | } 86 | 87 | static class ServicesHolder { 88 | 89 | final Map existingServices; 90 | 91 | final Map nonExistingServices; 92 | 93 | ServicesHolder(Map existingServices, Map nonExistingServices) { 94 | this.existingServices = existingServices; 95 | this.nonExistingServices = nonExistingServices; 96 | } 97 | 98 | } 99 | 100 | } 101 | -------------------------------------------------------------------------------- /src/test/java/org/springframework/guice/annotation/EnableGuiceModulesTests.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2013-2014 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.guice.annotation; 18 | 19 | import com.google.inject.AbstractModule; 20 | import com.google.inject.Injector; 21 | import com.google.inject.Provides; 22 | import com.google.inject.Singleton; 23 | import jakarta.inject.Inject; 24 | import jakarta.inject.Named; 25 | import org.junit.jupiter.api.AfterEach; 26 | import org.junit.jupiter.api.Test; 27 | 28 | import org.springframework.beans.factory.annotation.Autowired; 29 | import org.springframework.context.annotation.AnnotationConfigApplicationContext; 30 | import org.springframework.context.annotation.Bean; 31 | import org.springframework.context.annotation.ComponentScan.Filter; 32 | import org.springframework.context.annotation.Configuration; 33 | import org.springframework.context.annotation.FilterType; 34 | 35 | import static org.assertj.core.api.Assertions.assertThat; 36 | 37 | /** 38 | * @author Dave Syer 39 | * 40 | */ 41 | public class EnableGuiceModulesTests { 42 | 43 | @AfterEach 44 | public void cleanUp() { 45 | System.clearProperty("spring.guice.dedup"); 46 | } 47 | 48 | @Test 49 | public void test() { 50 | AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(TestConfig.class); 51 | assertThat(context.getBean(Foo.class)).isNotNull(); 52 | context.close(); 53 | } 54 | 55 | @Test 56 | public void testWithDedupFeatureEnabled() { 57 | System.setProperty("spring.guice.dedup", "true"); 58 | AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(TestConfig.class); 59 | assertThat(context.getBean(Foo.class)).isNotNull(); 60 | context.close(); 61 | } 62 | 63 | @Test 64 | public void module() { 65 | AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ModuleConfig.class); 66 | assertThat(context.getBean(Foo.class)).isNotNull(); 67 | context.close(); 68 | } 69 | 70 | @Test 71 | public void moduleBean() { 72 | AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ModuleBeanConfig.class); 73 | assertThat(context.getBean(Foo.class)).isNotNull(); 74 | context.close(); 75 | } 76 | 77 | @Test 78 | public void moduleBeanFiltersOutModules() { 79 | AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext( 80 | FilteringModuleBeanConfig.class); 81 | assertThat(context.getBean(Foo.class)).isNotNull(); 82 | context.close(); 83 | } 84 | 85 | @Test 86 | public void moduleBeanFiltersOutModulesWithMultipleFilters() { 87 | AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext( 88 | FilteringModuleBeanConfig.class, PermissiveModuleFilterConfig.class); 89 | assertThat(context.getBean(Foo.class)).isNotNull(); 90 | context.close(); 91 | } 92 | 93 | @Test 94 | public void testInjectorCreationDoesNotCauseCircularDependencyError() { 95 | AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MySpringConfig.class); 96 | assertThat(context.getBean(SpringProvidedBean.class)).isNotNull(); 97 | context.close(); 98 | } 99 | 100 | interface Service { 101 | 102 | } 103 | 104 | protected static class MyService implements Service { 105 | 106 | } 107 | 108 | public static class Foo { 109 | 110 | @Inject 111 | public Foo(@Named("service") Service service) { 112 | service.toString(); 113 | } 114 | 115 | } 116 | 117 | @Configuration 118 | @EnableGuiceModules 119 | @GuiceModule(excludeFilters = @Filter(type = FilterType.ASSIGNABLE_TYPE, value = Foo.class)) 120 | protected static class TestConfig { 121 | 122 | @Autowired 123 | private Injector injector; 124 | 125 | @Bean 126 | public Foo foo() { 127 | return this.injector.getInstance(Foo.class); 128 | } 129 | 130 | @Bean 131 | public Service service() { 132 | return new MyService(); 133 | } 134 | 135 | } 136 | 137 | @Configuration(proxyBeanMethods = false) 138 | @EnableGuiceModules 139 | protected static class ModuleConfig extends AbstractModule { 140 | 141 | @Override 142 | protected void configure() { 143 | bind(Service.class).to(MyService.class); 144 | } 145 | 146 | @Bean 147 | public Foo service(Service service) { 148 | return new Foo(service); 149 | } 150 | 151 | } 152 | 153 | @Configuration(proxyBeanMethods = false) 154 | @EnableGuiceModules 155 | protected static class ModuleBeanConfig { 156 | 157 | @Bean 158 | public static MyModule module() { 159 | return new MyModule(); 160 | } 161 | 162 | @Bean 163 | public Foo service(Service service) { 164 | return new Foo(service); 165 | } 166 | 167 | } 168 | 169 | @Configuration(proxyBeanMethods = false) 170 | @EnableGuiceModules 171 | protected static class FilteringModuleBeanConfig { 172 | 173 | @Bean 174 | public static MyModule2 module2() { 175 | return new MyModule2(); 176 | } 177 | 178 | @Bean 179 | public static MyModule module() { 180 | return new MyModule(); 181 | } 182 | 183 | @Bean 184 | public Foo service(Service service) { 185 | return new Foo(service); 186 | } 187 | 188 | @Bean 189 | static ModuleFilter moduleFilter() { 190 | return (module) -> !(module instanceof MyModule2); 191 | } 192 | 193 | } 194 | 195 | @Configuration 196 | static class PermissiveModuleFilterConfig { 197 | 198 | @Bean 199 | static ModuleFilter moduleFilter2() { 200 | return (module) -> true; 201 | } 202 | 203 | } 204 | 205 | protected static class MyModule extends AbstractModule { 206 | 207 | @Override 208 | protected void configure() { 209 | bind(Service.class).to(MyService.class); 210 | } 211 | 212 | } 213 | 214 | protected static class MyModule2 extends AbstractModule { 215 | 216 | @Override 217 | protected void configure() { 218 | throw new RuntimeException("This should not be called when filtered out!"); 219 | } 220 | 221 | } 222 | 223 | public static class SpringProvidedBean { 224 | 225 | public SpringProvidedBean(GuiceProvidedBean guiceProvidedBean) { 226 | } 227 | 228 | } 229 | 230 | public static class GuiceProvidedBean { 231 | 232 | } 233 | 234 | public static class GuiceService { 235 | 236 | @Inject 237 | public GuiceService(SpringProvidedBean springProvidedBean) { 238 | } 239 | 240 | } 241 | 242 | public static class MyGuiceModule extends AbstractModule { 243 | 244 | @Override 245 | protected void configure() { 246 | bind(GuiceService.class).asEagerSingleton(); 247 | } 248 | 249 | @Provides 250 | @Singleton 251 | public GuiceProvidedBean guiceProvidedBean() { 252 | return new GuiceProvidedBean(); 253 | } 254 | 255 | } 256 | 257 | @Configuration 258 | @EnableGuiceModules 259 | public static class MySpringConfig { 260 | 261 | @Bean 262 | public SpringProvidedBean baz(GuiceProvidedBean guiceProvidedBean) { 263 | return new SpringProvidedBean(guiceProvidedBean); 264 | } 265 | 266 | @Bean 267 | public static MyGuiceModule bazModule() { 268 | return new MyGuiceModule(); 269 | } 270 | 271 | } 272 | 273 | } 274 | -------------------------------------------------------------------------------- /src/test/java/org/springframework/guice/annotation/GuiceModuleAnnotationGenericTypeTests.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2013-2014 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.guice.annotation; 18 | 19 | import org.junit.jupiter.api.Test; 20 | 21 | import org.springframework.context.annotation.AnnotationConfigApplicationContext; 22 | import org.springframework.context.annotation.Bean; 23 | import org.springframework.context.annotation.Configuration; 24 | 25 | import static org.assertj.core.api.Assertions.assertThat; 26 | 27 | public class GuiceModuleAnnotationGenericTypeTests { 28 | 29 | @Test 30 | public void testBinding() { 31 | AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(TestConfig.class); 32 | assertThat(context.getBean(Foo.class)).isNotNull(); 33 | context.close(); 34 | } 35 | 36 | public interface Foo { 37 | 38 | T getValue(); 39 | 40 | } 41 | 42 | public static class FooImpl implements Foo { 43 | 44 | private final T payload; 45 | 46 | FooImpl(T payload) { 47 | this.payload = payload; 48 | } 49 | 50 | @Override 51 | public T getValue() { 52 | return this.payload; 53 | } 54 | 55 | } 56 | 57 | @Configuration 58 | @EnableGuiceModules 59 | @GuiceModule 60 | static class TestConfig { 61 | 62 | @Bean 63 | FooImpl fooBean() { 64 | return new FooImpl("foo.foo.foo"); 65 | } 66 | 67 | } 68 | 69 | } 70 | -------------------------------------------------------------------------------- /src/test/java/org/springframework/guice/annotation/GuiceModuleAnnotationTests.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2013-2014 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.guice.annotation; 18 | 19 | import java.util.HashMap; 20 | import java.util.Map; 21 | 22 | import com.google.inject.ConfigurationException; 23 | import com.google.inject.Guice; 24 | import com.google.inject.Injector; 25 | import org.junit.jupiter.api.Test; 26 | 27 | import org.springframework.beans.factory.annotation.Autowired; 28 | import org.springframework.context.annotation.AnnotationConfigApplicationContext; 29 | import org.springframework.context.annotation.Bean; 30 | import org.springframework.context.annotation.ComponentScan.Filter; 31 | import org.springframework.context.annotation.Configuration; 32 | import org.springframework.context.annotation.FilterType; 33 | import org.springframework.guice.module.SpringModule; 34 | 35 | import static org.assertj.core.api.Assertions.assertThat; 36 | import static org.assertj.core.api.Assertions.assertThatExceptionOfType; 37 | 38 | /** 39 | * @author Dave Syer 40 | * 41 | */ 42 | public class GuiceModuleAnnotationTests { 43 | 44 | @Test 45 | public void includes() throws Exception { 46 | Injector injector = createInjector(TestConfig.class, MetadataIncludesConfig.class); 47 | assertThat(injector.getBinding(Service.class)).isNotNull(); 48 | } 49 | 50 | @Test 51 | public void includesNames() throws Exception { 52 | Injector injector = createInjector(TestConfig.class, MetadataIncludeNamesConfig.class); 53 | assertThat(injector.getBinding(Service.class)).isNotNull(); 54 | } 55 | 56 | @Test 57 | public void includesPatterns() throws Exception { 58 | Injector injector = createInjector(TestConfig.class, MetadataIncludePatternsConfig.class); 59 | assertThat(injector.getBinding(Service.class)).isNotNull(); 60 | } 61 | 62 | @Test 63 | public void excludes() throws Exception { 64 | Injector injector = createInjector(TestConfig.class, MetadataExcludesConfig.class); 65 | assertThatExceptionOfType(ConfigurationException.class).isThrownBy(() -> injector.getInstance(Service.class)); 66 | } 67 | 68 | @Test 69 | public void excludesNames() throws Exception { 70 | Injector injector = createInjector(TestConfig.class, MetadataExcludeNamesConfig.class); 71 | assertThatExceptionOfType(ConfigurationException.class).isThrownBy(() -> injector.getBinding(Service.class)); 72 | } 73 | 74 | @Test 75 | public void excludesPatterns() throws Exception { 76 | Injector injector = createInjector(TestConfig.class, MetadataExcludePatternsConfig.class); 77 | assertThatExceptionOfType(ConfigurationException.class).isThrownBy(() -> injector.getBinding(Service.class)); 78 | } 79 | 80 | @Test 81 | public void twoIncludes() throws Exception { 82 | Injector injector = createInjector(TestConfig.class, MetadataIncludesConfig.class, 83 | MetadataMoreIncludesConfig.class); 84 | assertThat(injector.getBinding(Service.class)).isNotNull(); 85 | } 86 | 87 | private Injector createInjector(Class... config) { 88 | Injector injector = Guice.createInjector(new SpringModule(new AnnotationConfigApplicationContext(config))); 89 | return injector; 90 | } 91 | 92 | interface Service { 93 | 94 | } 95 | 96 | protected static class MyService implements Service { 97 | 98 | } 99 | 100 | public static class Foo { 101 | 102 | @Autowired 103 | public Foo(Service service) { 104 | } 105 | 106 | } 107 | 108 | @Configuration 109 | @GuiceModule(excludeFilters = @Filter(type = FilterType.REGEX, pattern = ".*")) 110 | protected static class MetadataExcludesConfig { 111 | 112 | } 113 | 114 | @Configuration 115 | @GuiceModule(excludeNames = "*") 116 | protected static class MetadataExcludeNamesConfig { 117 | 118 | } 119 | 120 | @Configuration 121 | @GuiceModule(excludePatterns = ".*") 122 | protected static class MetadataExcludePatternsConfig { 123 | 124 | } 125 | 126 | @Configuration 127 | @GuiceModule(includeFilters = @Filter(type = FilterType.ASSIGNABLE_TYPE, value = Service.class)) 128 | protected static class MetadataIncludesConfig { 129 | 130 | } 131 | 132 | @Configuration 133 | @GuiceModule(includeNames = "*service") // Bean name filter 134 | protected static class MetadataIncludeNamesConfig { 135 | 136 | } 137 | 138 | @Configuration 139 | @GuiceModule(includePatterns = ".*service") // Bean name filter 140 | protected static class MetadataIncludePatternsConfig { 141 | 142 | } 143 | 144 | @Configuration 145 | @GuiceModule(includeFilters = @Filter(type = FilterType.ASSIGNABLE_TYPE, value = Foo.class)) 146 | protected static class MetadataMoreIncludesConfig { 147 | 148 | } 149 | 150 | @Configuration 151 | public static class TestConfig { 152 | 153 | @Bean 154 | public Service service() { 155 | return new MyService(); 156 | } 157 | 158 | @Bean 159 | public Map someParameterizedType() { 160 | return new HashMap(); 161 | } 162 | 163 | } 164 | 165 | } 166 | -------------------------------------------------------------------------------- /src/test/java/org/springframework/guice/annotation/ModuleBeanWiringTests.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2013-2014 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.guice.annotation; 18 | 19 | import com.google.inject.AbstractModule; 20 | import com.google.inject.Injector; 21 | import com.google.inject.Provides; 22 | import jakarta.inject.Inject; 23 | import jakarta.inject.Named; 24 | import jakarta.inject.Singleton; 25 | import org.junit.jupiter.api.Test; 26 | 27 | import org.springframework.beans.factory.annotation.Autowired; 28 | import org.springframework.context.annotation.AnnotationConfigApplicationContext; 29 | import org.springframework.context.annotation.Bean; 30 | import org.springframework.context.annotation.Configuration; 31 | import org.springframework.guice.AbstractCompleteWiringTests; 32 | import org.springframework.guice.injector.SpringInjector; 33 | 34 | import static org.assertj.core.api.Assertions.assertThat; 35 | 36 | /** 37 | * @author Dave Syer 38 | * 39 | */ 40 | public class ModuleBeanWiringTests extends AbstractCompleteWiringTests { 41 | 42 | private AnnotationConfigApplicationContext context; 43 | 44 | @Override 45 | protected Injector createInjector() { 46 | this.context = new AnnotationConfigApplicationContext(); 47 | this.context.register(TestConfig.class); 48 | this.context.refresh(); 49 | return new SpringInjector(this.context); 50 | } 51 | 52 | @Test 53 | public void bindToSpringBeanFromGuiceModule() throws Exception { 54 | assertThat(this.context.getBean(Spam.class)).isNotNull(); 55 | } 56 | 57 | @EnableGuiceModules 58 | @Configuration(proxyBeanMethods = false) 59 | public static class TestConfig extends AbstractModule { 60 | 61 | @Autowired 62 | Service service; 63 | 64 | @Override 65 | protected void configure() { 66 | bind(Service.class).to(MyService.class); 67 | } 68 | 69 | @Bean 70 | public Spam spam(Service service) { 71 | return new Spam(service); 72 | } 73 | 74 | @Provides 75 | @Named("thing") 76 | public Thang thing() { 77 | return new Thang(); 78 | } 79 | 80 | @Provides 81 | @Inject 82 | @Singleton 83 | public Baz baz(Service service) { 84 | return new Baz(service); 85 | } 86 | 87 | @Bean 88 | public Parameterized parameterizedBean() { 89 | return new Parameterized() { 90 | }; 91 | } 92 | 93 | } 94 | 95 | protected static class Spam { 96 | 97 | public Spam(Service service) { 98 | } 99 | 100 | } 101 | 102 | } 103 | -------------------------------------------------------------------------------- /src/test/java/org/springframework/guice/annotation/ModuleNamedBeanWiringTests.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2013-2014 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.guice.annotation; 18 | 19 | import com.google.inject.AbstractModule; 20 | import com.google.inject.Injector; 21 | import com.google.inject.Provides; 22 | import jakarta.inject.Inject; 23 | import jakarta.inject.Named; 24 | import jakarta.inject.Singleton; 25 | import org.junit.jupiter.api.Test; 26 | 27 | import org.springframework.beans.factory.annotation.Autowired; 28 | import org.springframework.context.annotation.AnnotationConfigApplicationContext; 29 | import org.springframework.context.annotation.Bean; 30 | import org.springframework.context.annotation.Configuration; 31 | import org.springframework.guice.AbstractCompleteWiringTests; 32 | import org.springframework.guice.injector.SpringInjector; 33 | 34 | import static org.assertj.core.api.Assertions.assertThat; 35 | 36 | /** 37 | * @author Dave Syer 38 | * 39 | */ 40 | public class ModuleNamedBeanWiringTests extends AbstractCompleteWiringTests { 41 | 42 | private AnnotationConfigApplicationContext context; 43 | 44 | @Override 45 | protected Injector createInjector() { 46 | this.context = new AnnotationConfigApplicationContext(); 47 | this.context.register(TestConfig.class); 48 | this.context.refresh(); 49 | return new SpringInjector(this.context); 50 | } 51 | 52 | @Test 53 | public void bindToSpringBeanFromGuiceModule() throws Exception { 54 | assertThat(this.context.getBean(Spam.class)).isNotNull(); 55 | } 56 | 57 | @EnableGuiceModules 58 | @Configuration(proxyBeanMethods = false) 59 | public static class TestConfig extends AbstractModule { 60 | 61 | @Autowired 62 | Service service; 63 | 64 | @Override 65 | protected void configure() { 66 | bind(Service.class).to(MyService.class); 67 | } 68 | 69 | @Bean 70 | public Spam spam(Service service) { 71 | return new Spam(service); 72 | } 73 | 74 | @Provides 75 | @Named("thing") 76 | public Thang thing() { 77 | return new Thang(); 78 | } 79 | 80 | @Provides 81 | @Named("other") 82 | public Thang other() { 83 | return new Thang(); 84 | } 85 | 86 | @Provides 87 | @Inject 88 | @Singleton 89 | public Baz baz(Service service) { 90 | return new Baz(service); 91 | } 92 | 93 | @Bean 94 | public Parameterized parameterizedBean() { 95 | return new Parameterized() { 96 | }; 97 | } 98 | 99 | } 100 | 101 | protected static class Spam { 102 | 103 | public Spam(Service service) { 104 | } 105 | 106 | } 107 | 108 | } 109 | -------------------------------------------------------------------------------- /src/test/java/org/springframework/guice/injector/SpringInjectorTests.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2013-2014 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.guice.injector; 18 | 19 | import com.google.inject.Key; 20 | import com.google.inject.name.Names; 21 | import org.junit.jupiter.api.AfterEach; 22 | import org.junit.jupiter.api.Test; 23 | 24 | import org.springframework.beans.factory.NoUniqueBeanDefinitionException; 25 | import org.springframework.context.ApplicationContext; 26 | import org.springframework.context.annotation.AnnotationConfigApplicationContext; 27 | import org.springframework.context.annotation.Bean; 28 | import org.springframework.context.annotation.Configuration; 29 | import org.springframework.guice.AbstractCompleteWiringTests.Baz; 30 | import org.springframework.guice.AbstractCompleteWiringTests.MyService; 31 | import org.springframework.guice.AbstractCompleteWiringTests.Service; 32 | 33 | import static org.assertj.core.api.Assertions.assertThat; 34 | import static org.assertj.core.api.Assertions.assertThatExceptionOfType; 35 | 36 | public class SpringInjectorTests { 37 | 38 | private SpringInjector injector = new SpringInjector(create()); 39 | 40 | private AnnotationConfigApplicationContext context; 41 | 42 | @AfterEach 43 | public void close() { 44 | if (this.context != null) { 45 | this.context.close(); 46 | } 47 | } 48 | 49 | @Test 50 | public void instance() { 51 | assertThat(this.injector.getInstance(Service.class)).isNotNull(); 52 | } 53 | 54 | @Test 55 | public void multiple() { 56 | this.injector = new SpringInjector(create(Additional.class)); 57 | assertThatExceptionOfType(NoUniqueBeanDefinitionException.class) 58 | .isThrownBy(() -> this.injector.getInstance(Service.class)); 59 | } 60 | 61 | @Test 62 | public void named() { 63 | this.injector = new SpringInjector(create(Additional.class)); 64 | assertThat(this.injector.getInstance(Key.get(Service.class, Names.named("service")))).isNotNull(); 65 | } 66 | 67 | @Test 68 | public void provider() { 69 | assertThat(this.injector.getProvider(Service.class).get()).isNotNull(); 70 | } 71 | 72 | @Test 73 | public void bindNewObject() { 74 | assertThat(this.injector.getInstance(Baz.class)).isNotNull(); 75 | } 76 | 77 | private ApplicationContext create(Class... config) { 78 | AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(); 79 | context.register(TestConfig.class); 80 | if (config.length > 0) { 81 | context.register(config); 82 | } 83 | context.refresh(); 84 | this.context = context; 85 | return context; 86 | } 87 | 88 | @Configuration 89 | public static class Additional { 90 | 91 | @Bean 92 | public Service another() { 93 | return new MyService(); 94 | } 95 | 96 | } 97 | 98 | @Configuration 99 | public static class TestConfig { 100 | 101 | @Bean 102 | public Service service() { 103 | return new MyService(); 104 | } 105 | 106 | } 107 | 108 | } 109 | -------------------------------------------------------------------------------- /src/test/java/org/springframework/guice/injector/SpringWiringTests.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014-2022 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.guice.injector; 18 | 19 | import com.google.inject.Injector; 20 | 21 | import org.springframework.context.annotation.AnnotationConfigApplicationContext; 22 | import org.springframework.context.annotation.Bean; 23 | import org.springframework.context.annotation.Configuration; 24 | import org.springframework.guice.AbstractCompleteWiringTests; 25 | 26 | /** 27 | * @author Dave Syer 28 | * 29 | */ 30 | public class SpringWiringTests extends AbstractCompleteWiringTests { 31 | 32 | @Override 33 | protected Injector createInjector() { 34 | AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(); 35 | context.register(TestConfig.class); 36 | context.refresh(); 37 | return new SpringInjector(context); 38 | } 39 | 40 | @Configuration 41 | public static class TestConfig { 42 | 43 | @Bean 44 | public Service service() { 45 | return new MyService(); 46 | } 47 | 48 | @Bean 49 | public Thang thing() { 50 | return new Thang(); 51 | } 52 | 53 | @Bean 54 | public Thang other() { 55 | return new Thang(); 56 | } 57 | 58 | @Bean 59 | public Parameterized parameterizedBean() { 60 | return new Parameterized() { 61 | }; 62 | } 63 | 64 | } 65 | 66 | } 67 | -------------------------------------------------------------------------------- /src/test/java/org/springframework/guice/module/DevelepmentStageInjectorTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021-2022 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.guice.module; 18 | 19 | import java.util.List; 20 | 21 | import com.google.inject.AbstractModule; 22 | import com.google.inject.Guice; 23 | import com.google.inject.Injector; 24 | import com.google.inject.Module; 25 | import com.google.inject.Provides; 26 | import com.google.inject.Singleton; 27 | import com.google.inject.Stage; 28 | import org.junit.jupiter.api.AfterAll; 29 | import org.junit.jupiter.api.BeforeAll; 30 | import org.junit.jupiter.api.Test; 31 | 32 | import org.springframework.context.annotation.AnnotationConfigApplicationContext; 33 | import org.springframework.context.annotation.Bean; 34 | import org.springframework.context.annotation.Configuration; 35 | import org.springframework.guice.annotation.EnableGuiceModules; 36 | import org.springframework.guice.annotation.InjectorFactory; 37 | 38 | import static org.assertj.core.api.Assertions.assertThat; 39 | 40 | public class DevelepmentStageInjectorTest { 41 | 42 | @BeforeAll 43 | public static void init() { 44 | System.setProperty("spring.guice.stage", "DEVELOPMENT"); 45 | } 46 | 47 | @AfterAll 48 | public static void cleanup() { 49 | System.clearProperty("spring.guice.stage"); 50 | } 51 | 52 | @Test 53 | public void testLazyInitBean() { 54 | AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext( 55 | DevelepmentStageInjectorTest.ModulesConfig.class); 56 | TestGuiceModule testGuiceModule = context.getBean(TestGuiceModule.class); 57 | assertThat(testGuiceModule.getProviderExecuted()).isFalse(); 58 | GuiceToken guiceToken = context.getBean(GuiceToken.class); 59 | assertThat(testGuiceModule.getProviderExecuted()).isTrue(); 60 | context.close(); 61 | } 62 | 63 | @Configuration 64 | @EnableGuiceModules 65 | static class ModulesConfig { 66 | 67 | @Bean 68 | static TestGuiceModule testGuiceModule() { 69 | return new TestGuiceModule(); 70 | } 71 | 72 | @Bean 73 | InjectorFactory injectorFactory() { 74 | return new TestDevelopmentStageInjectorFactory(); 75 | } 76 | 77 | } 78 | 79 | static class TestGuiceModule extends AbstractModule { 80 | 81 | private boolean providerExecuted = false; 82 | 83 | boolean getProviderExecuted() { 84 | return this.providerExecuted; 85 | } 86 | 87 | @Override 88 | protected void configure() { 89 | } 90 | 91 | @Provides 92 | @Singleton 93 | GuiceToken guiceToken() { 94 | this.providerExecuted = true; 95 | return new GuiceToken(); 96 | } 97 | 98 | } 99 | 100 | static class TestDevelopmentStageInjectorFactory implements InjectorFactory { 101 | 102 | @Override 103 | public Injector createInjector(List modules) { 104 | return Guice.createInjector(Stage.DEVELOPMENT, modules); 105 | } 106 | 107 | } 108 | 109 | static class GuiceToken { 110 | 111 | } 112 | 113 | } 114 | -------------------------------------------------------------------------------- /src/test/java/org/springframework/guice/module/SpringModuleGuiceBindingAwareTests.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2017 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.guice.module; 18 | 19 | import com.google.inject.AbstractModule; 20 | import com.google.inject.Guice; 21 | import com.google.inject.Injector; 22 | import com.google.inject.Scopes; 23 | import com.google.inject.util.Providers; 24 | import jakarta.inject.Inject; 25 | import org.junit.jupiter.api.Test; 26 | 27 | import org.springframework.context.ApplicationEvent; 28 | import org.springframework.context.ApplicationListener; 29 | import org.springframework.context.annotation.Bean; 30 | import org.springframework.context.annotation.Configuration; 31 | import org.springframework.test.util.AopTestUtils; 32 | 33 | import static org.assertj.core.api.Assertions.assertThat; 34 | 35 | public class SpringModuleGuiceBindingAwareTests { 36 | 37 | @Test 38 | public void testAllDependenciesInjectedAndLifeycleMethodsCalledOnce() { 39 | Injector injector = Guice.createInjector(new SimpleGuiceModule(), 40 | new SpringModule(BeanFactoryProvider.from(GuiceProjectWithSpringLibraryTestSpringConfig.class))); 41 | 42 | // check guice provided bindings 43 | assertThat(injector.getInstance(GuiceDependency1.class)).isNotNull(); 44 | assertThat(injector.getInstance(IGuiceDependency1.class)).isNotNull(); 45 | 46 | // check spring bindings as interface 47 | ISpringBean springBean = injector.getInstance(ISpringBean.class); 48 | assertThat(springBean).isNotNull(); 49 | assertThat(springBean.getDep1()).isNotNull(); 50 | assertThat(springBean.getDep2()).isNotNull(); 51 | assertThat(springBean.getDep3()).isNotNull(); 52 | 53 | // invoke a method to make sure we aren't dealing with a lazy proxy 54 | assertThat(springBean.getDep1().doWork()).isEqualTo("done"); 55 | 56 | // check binding equality 57 | assertThat(injector.getInstance(IGuiceDependency1.class)) 58 | .isSameAs(AopTestUtils.getTargetObject(springBean.getDep1())); 59 | assertThat(injector.getInstance(IGuiceDependency2.class)) 60 | .isSameAs(AopTestUtils.getTargetObject(springBean.getDep2())); 61 | assertThat(injector.getInstance(IGuiceDependency3.class)) 62 | .isSameAs(AopTestUtils.getTargetObject(springBean.getDep3())); 63 | } 64 | 65 | static class SimpleGuiceModule extends AbstractModule { 66 | 67 | @Override 68 | protected void configure() { 69 | // test normal binding 70 | bind(IGuiceDependency1.class).to(GuiceDependency1.class).in(Scopes.SINGLETON); 71 | // test instance binding 72 | bind(IGuiceDependency2.class).toInstance(new IGuiceDependency2() { 73 | }); 74 | // test provider binding 75 | bind(IGuiceDependency3.class).toProvider(Providers.of(new IGuiceDependency3() { 76 | })); 77 | } 78 | 79 | } 80 | 81 | @Configuration 82 | static class GuiceProjectWithSpringLibraryTestSpringConfig { 83 | 84 | @Bean 85 | ISpringBean springDefinedSomething(IGuiceDependency1 dependency) { 86 | return new SpringBean(dependency); 87 | } 88 | 89 | @Bean 90 | ApplicationListener eventListener(final IGuiceDependency1 dependency) { 91 | return new ApplicationListener() { 92 | @Override 93 | public void onApplicationEvent(ApplicationEvent event) { 94 | dependency.doWork(); 95 | } 96 | }; 97 | } 98 | 99 | } 100 | 101 | interface IGuiceDependency1 { 102 | 103 | String doWork(); 104 | 105 | } 106 | 107 | interface IGuiceDependency2 { 108 | 109 | } 110 | 111 | interface IGuiceDependency3 { 112 | 113 | } 114 | 115 | static class GuiceDependency1 implements IGuiceDependency1 { 116 | 117 | @Override 118 | public String doWork() { 119 | return "done"; 120 | } 121 | 122 | } 123 | 124 | interface ISpringBean { 125 | 126 | IGuiceDependency1 getDep1(); 127 | 128 | IGuiceDependency2 getDep2(); 129 | 130 | IGuiceDependency3 getDep3(); 131 | 132 | } 133 | 134 | static class SpringBean implements ISpringBean { 135 | 136 | private final IGuiceDependency1 dep1; 137 | 138 | @Inject 139 | private IGuiceDependency2 dep2; 140 | 141 | @Inject 142 | private IGuiceDependency3 dep3; 143 | 144 | @Inject 145 | SpringBean(IGuiceDependency1 dependency) { 146 | this.dep1 = dependency; 147 | } 148 | 149 | @Override 150 | public IGuiceDependency1 getDep1() { 151 | return this.dep1; 152 | } 153 | 154 | @Override 155 | public IGuiceDependency2 getDep2() { 156 | return this.dep2; 157 | } 158 | 159 | @Override 160 | public IGuiceDependency3 getDep3() { 161 | return this.dep3; 162 | } 163 | 164 | } 165 | 166 | } 167 | -------------------------------------------------------------------------------- /src/test/java/org/springframework/guice/module/SpringModuleMetadataTests.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2013-2014 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.guice.module; 18 | 19 | import java.lang.annotation.Retention; 20 | import java.lang.annotation.RetentionPolicy; 21 | 22 | import com.google.inject.ConfigurationException; 23 | import com.google.inject.Guice; 24 | import com.google.inject.Injector; 25 | import com.google.inject.Key; 26 | import com.google.inject.ProvisionException; 27 | import com.google.inject.name.Names; 28 | import jakarta.inject.Inject; 29 | import jakarta.inject.Named; 30 | import jakarta.inject.Qualifier; 31 | import org.junit.jupiter.api.Test; 32 | 33 | import org.springframework.cache.annotation.Cacheable; 34 | import org.springframework.context.annotation.AnnotationConfigApplicationContext; 35 | import org.springframework.context.annotation.Bean; 36 | import org.springframework.context.annotation.Configuration; 37 | import org.springframework.context.annotation.Primary; 38 | import org.springframework.core.type.filter.AnnotationTypeFilter; 39 | import org.springframework.core.type.filter.AssignableTypeFilter; 40 | 41 | import static org.assertj.core.api.Assertions.assertThat; 42 | import static org.assertj.core.api.Assertions.assertThatCode; 43 | import static org.assertj.core.api.Assertions.assertThatExceptionOfType; 44 | 45 | /** 46 | * @author Dave Syer 47 | * 48 | */ 49 | public class SpringModuleMetadataTests { 50 | 51 | @Test 52 | public void twoConfigClasses() throws Exception { 53 | Injector injector = createInjector(TestConfig.class, OtherConfig.class); 54 | assertThat(injector.getInstance(Service.class)).isNotNull(); 55 | } 56 | 57 | @Test 58 | public void twoServices() throws Exception { 59 | Injector injector = createInjector(TestConfig.class, MoreConfig.class); 60 | assertThatExceptionOfType(ProvisionException.class) 61 | .isThrownBy(() -> assertThat(injector.getInstance(Service.class)).isNotNull()); 62 | } 63 | 64 | @Test 65 | public void twoServicesOnePrimary() throws Exception { 66 | Injector injector = createInjector(TestConfig.class, PrimaryConfig.class); 67 | assertThat(injector.getInstance(Service.class)).isNotNull(); 68 | } 69 | 70 | @Test 71 | public void twoServicesByName() throws Exception { 72 | Injector injector = createInjector(TestConfig.class, MoreConfig.class); 73 | assertThat(injector.getInstance(Key.get(Service.class, Names.named("service")))).isNotNull(); 74 | } 75 | 76 | @Test 77 | public void threeServicesByQualifier() throws Exception { 78 | Injector injector = createInjector(PrimaryConfig.class, QualifiedConfig.class); 79 | 80 | assertThat(injector.getInstance( 81 | Key.get(Service.class, ServiceQualifierAnnotated.class.getAnnotation(ServiceQualifier.class)))) 82 | .extracting("name").isEqualTo("emptyQualifierService"); 83 | 84 | assertThat(injector.getInstance( 85 | Key.get(Service.class, EmptyServiceQualifierAnnotated.class.getAnnotation(ServiceQualifier.class)))) 86 | .extracting("name").isEqualTo("emptyQualifierService"); 87 | 88 | assertThat(injector.getInstance( 89 | Key.get(Service.class, MyServiceQualifierAnnotated.class.getAnnotation(ServiceQualifier.class)))) 90 | .extracting("name").isEqualTo("myService"); 91 | 92 | assertThat(injector.getInstance(Key.get(Service.class, Names.named("namedService")))).extracting("name") 93 | .isEqualTo("namedService"); 94 | 95 | assertThat(injector.getInstance(Key.get(Service.class, Names.named("namedServiceWithADifferentBeanName")))) 96 | .extracting("name").isEqualTo("namedServiceWithADifferentBeanName"); 97 | 98 | assertThat(injector.getInstance(Service.class)).extracting("name").isEqualTo("primary"); 99 | 100 | // Test cases where we don't expect to find any bindings 101 | assertThatCode(() -> injector.getInstance(Key.get(Service.class, Names.named("randomService")))) 102 | .isInstanceOf(ConfigurationException.class); 103 | 104 | assertThatCode(() -> injector.getInstance( 105 | Key.get(Service.class, NoServiceQualifierAnnotated.class.getAnnotation(ServiceQualifier.class)))) 106 | .isInstanceOf(ConfigurationException.class); 107 | 108 | assertThatCode(() -> injector.getInstance(Key.get(Service.class, UnboundServiceQualifier.class))) 109 | .isInstanceOf(ConfigurationException.class); 110 | 111 | } 112 | 113 | @Test 114 | public void includes() throws Exception { 115 | Injector injector = createInjector(TestConfig.class, MetadataIncludesConfig.class); 116 | assertThatExceptionOfType(ConfigurationException.class) 117 | .isThrownBy(() -> assertThat(injector.getBinding(Service.class)).isNull()); 118 | } 119 | 120 | @Test 121 | public void excludes() throws Exception { 122 | Injector injector = createInjector(TestConfig.class, MetadataExcludesConfig.class); 123 | assertThatExceptionOfType(ConfigurationException.class) 124 | .isThrownBy(() -> assertThat(injector.getBinding(Service.class)).isNull()); 125 | } 126 | 127 | private Injector createInjector(Class... config) { 128 | AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(); 129 | context.register(config); 130 | context.refresh(); 131 | return Guice.createInjector(new SpringModule(context)); 132 | } 133 | 134 | interface Service { 135 | 136 | String getName(); 137 | 138 | } 139 | 140 | protected static class MyService implements Service { 141 | 142 | private final String name; 143 | 144 | protected MyService(String name) { 145 | this.name = name; 146 | } 147 | 148 | @Override 149 | public String getName() { 150 | return this.name; 151 | } 152 | 153 | } 154 | 155 | public static class Foo { 156 | 157 | @Inject 158 | public Foo(Service service) { 159 | } 160 | 161 | } 162 | 163 | @Configuration 164 | protected static class MetadataExcludesConfig { 165 | 166 | @Bean 167 | public GuiceModuleMetadata guiceModuleMetadata() { 168 | GuiceModuleMetadata metadata = new GuiceModuleMetadata(); 169 | metadata.exclude(new AssignableTypeFilter(Service.class)); 170 | return metadata; 171 | } 172 | 173 | } 174 | 175 | @Configuration 176 | protected static class MetadataIncludesConfig { 177 | 178 | @Bean 179 | public GuiceModuleMetadata guiceModuleMetadata() { 180 | GuiceModuleMetadata metadata = new GuiceModuleMetadata(); 181 | metadata.include(new AnnotationTypeFilter(Cacheable.class)); 182 | return metadata; 183 | } 184 | 185 | } 186 | 187 | @Configuration 188 | public static class TestConfig { 189 | 190 | @Bean 191 | public Service service() { 192 | return new MyService("service"); 193 | } 194 | 195 | } 196 | 197 | @Configuration 198 | public static class PrimaryConfig { 199 | 200 | @Bean 201 | @Primary 202 | public Service primary() { 203 | return new MyService("primary"); 204 | } 205 | 206 | } 207 | 208 | @Configuration 209 | public static class MoreConfig { 210 | 211 | @Bean 212 | public Service more() { 213 | return new MyService("more"); 214 | } 215 | 216 | } 217 | 218 | @Configuration 219 | public static class QualifiedConfig { 220 | 221 | @Bean 222 | @Named("namedService") 223 | public Service namedService() { 224 | return new MyService("namedService"); 225 | } 226 | 227 | @Bean 228 | @Named("namedServiceWithADifferentBeanName") 229 | public Service anotherNamedService() { 230 | return new MyService("namedServiceWithADifferentBeanName"); 231 | } 232 | 233 | @Bean 234 | @ServiceQualifier 235 | public Service emptyQualifierService() { 236 | return new MyService("emptyQualifierService"); 237 | } 238 | 239 | @Bean 240 | @ServiceQualifier(type = "myService") 241 | public Service myService(@Named("namedService") Service service) { 242 | return new MyService("myService"); 243 | } 244 | 245 | } 246 | 247 | @Configuration 248 | public static class OtherConfig { 249 | 250 | } 251 | 252 | @Qualifier 253 | @Retention(RetentionPolicy.RUNTIME) 254 | @interface ServiceQualifier { 255 | 256 | String type() default ""; 257 | 258 | } 259 | 260 | @Qualifier 261 | @Retention(RetentionPolicy.RUNTIME) 262 | @interface UnboundServiceQualifier { 263 | 264 | } 265 | 266 | @ServiceQualifier 267 | interface ServiceQualifierAnnotated { 268 | 269 | } 270 | 271 | @ServiceQualifier(type = "") 272 | interface EmptyServiceQualifierAnnotated { 273 | 274 | } 275 | 276 | @ServiceQualifier(type = "myService") 277 | interface MyServiceQualifierAnnotated { 278 | 279 | } 280 | 281 | @ServiceQualifier(type = "noService") 282 | interface NoServiceQualifierAnnotated { 283 | 284 | } 285 | 286 | } 287 | -------------------------------------------------------------------------------- /src/test/java/org/springframework/guice/module/SpringModuleWiringTests.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2013-2014 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.guice.module; 18 | 19 | import com.google.inject.Guice; 20 | import com.google.inject.Injector; 21 | 22 | import org.springframework.context.annotation.AnnotationConfigApplicationContext; 23 | import org.springframework.context.annotation.Bean; 24 | import org.springframework.context.annotation.Configuration; 25 | import org.springframework.guice.AbstractCompleteWiringTests; 26 | 27 | /** 28 | * @author Dave Syer 29 | * 30 | */ 31 | public class SpringModuleWiringTests extends AbstractCompleteWiringTests { 32 | 33 | @Override 34 | protected Injector createInjector() { 35 | return Guice.createInjector(new SpringModule(new AnnotationConfigApplicationContext(TestConfig.class))); 36 | } 37 | 38 | @Configuration 39 | public static class TestConfig { 40 | 41 | @Bean 42 | public Service service() { 43 | return new MyService(); 44 | } 45 | 46 | @Bean 47 | public Baz baz() { 48 | return new Baz(service()); 49 | } 50 | 51 | @Bean 52 | public Thang thing() { 53 | return new Thang(); 54 | } 55 | 56 | @Bean 57 | public Thing that() { 58 | return new Thing(); 59 | } 60 | 61 | @Bean 62 | public Parameterized parameterizedBean() { 63 | return new Parameterized() { 64 | }; 65 | } 66 | 67 | } 68 | 69 | } 70 | -------------------------------------------------------------------------------- /src/test/java/org/springframework/guice/module/SpringModuleWrappedTests.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014-2022 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.guice.module; 18 | 19 | import com.google.inject.AbstractModule; 20 | import com.google.inject.Guice; 21 | import com.google.inject.Injector; 22 | import jakarta.inject.Inject; 23 | import jakarta.inject.Named; 24 | import org.junit.jupiter.api.Test; 25 | 26 | import org.springframework.context.annotation.Bean; 27 | import org.springframework.context.annotation.Configuration; 28 | import org.springframework.guice.annotation.EnableGuiceModules; 29 | 30 | import static org.assertj.core.api.Assertions.assertThat; 31 | 32 | public class SpringModuleWrappedTests { 33 | 34 | @Test 35 | public void testDependenciesFromWrappedModule() { 36 | Injector injector = Guice.createInjector( 37 | new SpringModule(BeanFactoryProvider.from(TestConfig.class, ModuleProviderConfig.class))); 38 | assertThat(injector.getInstance(Baz.class)).isNotNull(); 39 | } 40 | 41 | @Configuration 42 | public static class TestConfig { 43 | 44 | @Bean 45 | public Baz baz(Service service) { 46 | return new Baz(service); 47 | } 48 | 49 | } 50 | 51 | interface Service { 52 | 53 | } 54 | 55 | protected static class MyService implements Service { 56 | 57 | } 58 | 59 | public static class Foo { 60 | 61 | @Inject 62 | public Foo(@Named("service") Service service) { 63 | service.toString(); 64 | } 65 | 66 | } 67 | 68 | public static class Baz { 69 | 70 | @Inject 71 | public Baz(Service service) { 72 | } 73 | 74 | } 75 | 76 | @Configuration 77 | @EnableGuiceModules 78 | protected static class ModuleProviderConfig { 79 | 80 | @Bean 81 | public static ProviderModule module() { 82 | return new ProviderModule(); 83 | } 84 | 85 | @Bean 86 | public Foo service(Service service) { 87 | return new Foo(service); 88 | } 89 | 90 | } 91 | 92 | protected static class ProviderModule extends AbstractModule { 93 | 94 | @Override 95 | protected void configure() { 96 | bind(Service.class).toProvider(() -> new MyService()); 97 | } 98 | 99 | } 100 | 101 | } 102 | --------------------------------------------------------------------------------