├── .springjavaformatconfig
├── .mvn
├── wrapper
│ ├── maven-wrapper.jar
│ └── maven-wrapper.properties
└── settings.xml
├── .gitignore
├── config
└── checkstyle
│ └── checkstyle.xml
├── src
├── main
│ ├── resources
│ │ └── META-INF
│ │ │ └── additional-spring-configuration-metadata.json
│ └── java
│ │ └── org
│ │ └── springframework
│ │ └── guice
│ │ ├── module
│ │ ├── BindingTypeMatcher.java
│ │ ├── GuiceModuleMetadata.java
│ │ ├── GuiceAutowireCandidateResolver.java
│ │ └── BeanFactoryProvider.java
│ │ ├── annotation
│ │ ├── InjectorFactory.java
│ │ ├── ModuleFilter.java
│ │ ├── EnableGuiceModules.java
│ │ ├── GuiceFactoryBean.java
│ │ ├── GuiceModule.java
│ │ └── GuiceModuleRegistrar.java
│ │ └── injector
│ │ └── SpringInjector.java
└── test
│ └── java
│ └── org
│ └── springframework
│ └── guice
│ ├── AdhocTestSuite.java
│ ├── NativeGuiceTests.java
│ ├── GuiceWiringTests.java
│ ├── injector
│ ├── SpringWiringTests.java
│ └── SpringInjectorTests.java
│ ├── annotation
│ ├── GuiceModuleAnnotationGenericTypeTests.java
│ ├── ModuleBeanWiringTests.java
│ ├── ModuleNamedBeanWiringTests.java
│ ├── GuiceModuleAnnotationTests.java
│ └── EnableGuiceModulesTests.java
│ ├── module
│ ├── SpringModuleWiringTests.java
│ ├── SpringModuleWrappedTests.java
│ ├── DevelepmentStageInjectorTest.java
│ ├── SpringModuleGuiceBindingAwareTests.java
│ └── SpringModuleMetadataTests.java
│ ├── MapWiringTests.java
│ ├── JustInTimeBindingTests.java
│ ├── PrototypeScopedBeanTests.java
│ ├── SimpleWiringTests.java
│ ├── InjectorFactoryTests.java
│ ├── SpringAutowiredCollectionTests.java
│ ├── SetBindingTests.java
│ ├── LazyInitializationTests.java
│ ├── ModuleFilteringTests.java
│ ├── ProvidesSupplierWiringTests.java
│ ├── ScopingTests.java
│ ├── AbstractCompleteWiringTests.java
│ ├── ElementVisitorTests.java
│ ├── DuplicateNamesDifferentTypesTests.java
│ ├── PrivateModuleTests.java
│ ├── MapBindingDeduplicationTests.java
│ ├── BeanPostProcessorTests.java
│ ├── PartialInjectionTests.java
│ └── BindingDeduplicationTests.java
├── .github
└── workflows
│ ├── maven.yml
│ └── push.yml
├── mvnw.cmd
├── mvnw
├── pom.xml
└── README.md
/.springjavaformatconfig:
--------------------------------------------------------------------------------
1 | java-baseline=8
--------------------------------------------------------------------------------
/.mvn/wrapper/maven-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/spring-projects/spring-guice/HEAD/.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 |
--------------------------------------------------------------------------------
/.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 |
--------------------------------------------------------------------------------
/config/checkstyle/checkstyle.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/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 | }
--------------------------------------------------------------------------------
/.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 |
--------------------------------------------------------------------------------
/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/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/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 |
--------------------------------------------------------------------------------
/.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 |
--------------------------------------------------------------------------------
/.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 |
--------------------------------------------------------------------------------
/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/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/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/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/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/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/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/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/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/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/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/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 |
--------------------------------------------------------------------------------
/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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/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/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/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/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/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 super T> 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 extends Module> 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/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 extends TypeFilter> includeFilters;
175 |
176 | private Collection extends TypeFilter> 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 extends TypeFilter> includeFilters) {
187 | this.includeFilters = includeFilters;
188 | }
189 |
190 | public void setExcludeFilters(Collection extends TypeFilter> 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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 | 
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 |
--------------------------------------------------------------------------------