mirror of
https://github.com/google/guice.git
synced 2024-04-21 12:32:36 +00:00
In Java 15, the annotation `toString` implementation omits the member name. PiperOrigin-RevId: 338746927
867 lines
25 KiB
Java
867 lines
25 KiB
Java
/*
|
|
* Copyright (C) 2008 Google Inc.
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
package com.google.inject;
|
|
|
|
import static com.google.inject.Asserts.assertContains;
|
|
import static com.google.inject.name.Names.named;
|
|
import static java.lang.annotation.ElementType.METHOD;
|
|
import static java.lang.annotation.ElementType.TYPE;
|
|
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
|
|
|
import com.google.common.collect.ImmutableList;
|
|
import com.google.common.collect.Lists;
|
|
import com.google.inject.binder.AnnotatedBindingBuilder;
|
|
import com.google.inject.binder.ScopedBindingBuilder;
|
|
import com.google.inject.name.Named;
|
|
import com.google.inject.util.Providers;
|
|
import java.lang.annotation.Retention;
|
|
import java.lang.annotation.Target;
|
|
import java.util.Collections;
|
|
import java.util.List;
|
|
import java.util.concurrent.atomic.AtomicInteger;
|
|
import junit.framework.Test;
|
|
import junit.framework.TestCase;
|
|
import junit.framework.TestSuite;
|
|
|
|
/** @author jessewilson@google.com (Jesse Wilson) */
|
|
public class BinderTestSuite extends TestCase {
|
|
|
|
public static Test suite() {
|
|
TestSuite suite = new TestSuite();
|
|
|
|
new Builder()
|
|
.name("bind A")
|
|
.module(
|
|
new AbstractModule() {
|
|
@Override
|
|
protected void configure() {
|
|
bind(A.class);
|
|
}
|
|
})
|
|
.creationException("No implementation for BinderTestSuite$A was bound.")
|
|
.addToSuite(suite);
|
|
|
|
new Builder()
|
|
.name("bind PlainA named apple")
|
|
.module(
|
|
new AbstractModule() {
|
|
@Override
|
|
protected void configure() {
|
|
bind(PlainA.class).annotatedWith(named("apple"));
|
|
}
|
|
})
|
|
.creationException(
|
|
"No implementation for BinderTestSuite$PlainA annotated with "
|
|
+ shortNamed(named("apple"))
|
|
+ " was bound")
|
|
.addToSuite(suite);
|
|
|
|
new Builder()
|
|
.name("bind A to new PlainA(1)")
|
|
.module(
|
|
new AbstractModule() {
|
|
@Override
|
|
protected void configure() {
|
|
bind(A.class).toInstance(new PlainA(1));
|
|
}
|
|
})
|
|
.creationTime(CreationTime.NONE)
|
|
.expectedValues(new PlainA(1), new PlainA(1), new PlainA(1))
|
|
.addToSuite(suite);
|
|
|
|
new Builder()
|
|
.name("no binding, AWithProvidedBy")
|
|
.key(Key.get(AWithProvidedBy.class), InjectsAWithProvidedBy.class)
|
|
.addToSuite(suite);
|
|
|
|
new Builder()
|
|
.name("no binding, AWithImplementedBy")
|
|
.key(Key.get(AWithImplementedBy.class), InjectsAWithImplementedBy.class)
|
|
.addToSuite(suite);
|
|
|
|
new Builder()
|
|
.name("no binding, ScopedA")
|
|
.key(Key.get(ScopedA.class), InjectsScopedA.class)
|
|
.expectedValues(new PlainA(201), new PlainA(201), new PlainA(202), new PlainA(202))
|
|
.addToSuite(suite);
|
|
|
|
new Builder()
|
|
.name("no binding, AWithProvidedBy named apple")
|
|
.key(Key.get(AWithProvidedBy.class, named("apple")), InjectsAWithProvidedByNamedApple.class)
|
|
.configurationException(
|
|
"No implementation for BinderTestSuite$AWithProvidedBy annotated with "
|
|
+ shortNamed(named("apple"))
|
|
+ " was bound")
|
|
.addToSuite(suite);
|
|
|
|
new Builder()
|
|
.name("no binding, AWithImplementedBy named apple")
|
|
.key(
|
|
Key.get(AWithImplementedBy.class, named("apple")),
|
|
InjectsAWithImplementedByNamedApple.class)
|
|
.configurationException(
|
|
"No implementation for BinderTestSuite$AWithImplementedBy annotated with "
|
|
+ shortNamed(named("apple"))
|
|
+ " was bound")
|
|
.addToSuite(suite);
|
|
|
|
new Builder()
|
|
.name("no binding, ScopedA named apple")
|
|
.key(Key.get(ScopedA.class, named("apple")), InjectsScopedANamedApple.class)
|
|
.configurationException(
|
|
"No implementation for BinderTestSuite$ScopedA annotated with "
|
|
+ shortNamed(named("apple"))
|
|
+ " was bound")
|
|
.addToSuite(suite);
|
|
|
|
for (final Scoper scoper : Scoper.values()) {
|
|
new Builder()
|
|
.name("bind PlainA")
|
|
.key(Key.get(PlainA.class), InjectsPlainA.class)
|
|
.module(
|
|
new AbstractModule() {
|
|
@Override
|
|
protected void configure() {
|
|
AnnotatedBindingBuilder<PlainA> abb = bind(PlainA.class);
|
|
scoper.configure(abb);
|
|
}
|
|
})
|
|
.scoper(scoper)
|
|
.addToSuite(suite);
|
|
|
|
new Builder()
|
|
.name("bind A to PlainA")
|
|
.module(
|
|
new AbstractModule() {
|
|
@Override
|
|
protected void configure() {
|
|
ScopedBindingBuilder sbb = bind(A.class).to(PlainA.class);
|
|
scoper.configure(sbb);
|
|
}
|
|
})
|
|
.scoper(scoper)
|
|
.addToSuite(suite);
|
|
|
|
new Builder()
|
|
.name("bind A to PlainAProvider.class")
|
|
.module(
|
|
new AbstractModule() {
|
|
@Override
|
|
protected void configure() {
|
|
ScopedBindingBuilder sbb = bind(A.class).toProvider(PlainAProvider.class);
|
|
scoper.configure(sbb);
|
|
}
|
|
})
|
|
.scoper(scoper)
|
|
.addToSuite(suite);
|
|
|
|
new Builder()
|
|
.name("bind A to new PlainAProvider()")
|
|
.module(
|
|
new AbstractModule() {
|
|
@Override
|
|
protected void configure() {
|
|
ScopedBindingBuilder sbb = bind(A.class).toProvider(new PlainAProvider());
|
|
scoper.configure(sbb);
|
|
}
|
|
})
|
|
.scoper(scoper)
|
|
.addToSuite(suite);
|
|
|
|
new Builder()
|
|
.name("bind AWithProvidedBy")
|
|
.key(Key.get(AWithProvidedBy.class), InjectsAWithProvidedBy.class)
|
|
.module(
|
|
new AbstractModule() {
|
|
@Override
|
|
protected void configure() {
|
|
ScopedBindingBuilder sbb = bind(AWithProvidedBy.class);
|
|
scoper.configure(sbb);
|
|
}
|
|
})
|
|
.scoper(scoper)
|
|
.addToSuite(suite);
|
|
|
|
new Builder()
|
|
.name("bind AWithImplementedBy")
|
|
.key(Key.get(AWithImplementedBy.class), InjectsAWithImplementedBy.class)
|
|
.module(
|
|
new AbstractModule() {
|
|
@Override
|
|
protected void configure() {
|
|
ScopedBindingBuilder sbb = bind(AWithImplementedBy.class);
|
|
scoper.configure(sbb);
|
|
}
|
|
})
|
|
.scoper(scoper)
|
|
.addToSuite(suite);
|
|
|
|
new Builder()
|
|
.name("bind ScopedA")
|
|
.key(Key.get(ScopedA.class), InjectsScopedA.class)
|
|
.module(
|
|
new AbstractModule() {
|
|
@Override
|
|
protected void configure() {
|
|
ScopedBindingBuilder sbb = bind(ScopedA.class);
|
|
scoper.configure(sbb);
|
|
}
|
|
})
|
|
.expectedValues(new PlainA(201), new PlainA(201), new PlainA(202), new PlainA(202))
|
|
.scoper(scoper)
|
|
.addToSuite(suite);
|
|
|
|
new Builder()
|
|
.name("bind AWithProvidedBy named apple")
|
|
.module(
|
|
new AbstractModule() {
|
|
@Override
|
|
protected void configure() {
|
|
scoper.configure(bind(AWithProvidedBy.class).annotatedWith(named("apple")));
|
|
}
|
|
})
|
|
.creationException(
|
|
"No implementation for BinderTestSuite$AWithProvidedBy annotated with "
|
|
+ shortNamed(named("apple"))
|
|
+ " was bound")
|
|
.scoper(scoper)
|
|
.addToSuite(suite);
|
|
|
|
new Builder()
|
|
.name("bind AWithImplementedBy named apple")
|
|
.module(
|
|
new AbstractModule() {
|
|
@Override
|
|
protected void configure() {
|
|
scoper.configure(bind(AWithImplementedBy.class).annotatedWith(named("apple")));
|
|
}
|
|
})
|
|
.creationException(
|
|
"No implementation for BinderTestSuite$AWithImplementedBy annotated with "
|
|
+ shortNamed(named("apple"))
|
|
+ " was bound")
|
|
.scoper(scoper)
|
|
.addToSuite(suite);
|
|
|
|
new Builder()
|
|
.name("bind ScopedA named apple")
|
|
.module(
|
|
new AbstractModule() {
|
|
@Override
|
|
protected void configure() {
|
|
scoper.configure(bind(ScopedA.class).annotatedWith(named("apple")));
|
|
}
|
|
})
|
|
.creationException(
|
|
"No implementation for BinderTestSuite$ScopedA annotated with "
|
|
+ shortNamed(named("apple"))
|
|
+ " was bound")
|
|
.scoper(scoper)
|
|
.addToSuite(suite);
|
|
}
|
|
|
|
return suite;
|
|
}
|
|
|
|
enum Scoper {
|
|
UNSCOPED {
|
|
@Override
|
|
void configure(ScopedBindingBuilder sbb) {}
|
|
|
|
@Override
|
|
void apply(Builder builder) {}
|
|
},
|
|
|
|
EAGER_SINGLETON {
|
|
@Override
|
|
void configure(ScopedBindingBuilder sbb) {
|
|
sbb.asEagerSingleton();
|
|
}
|
|
|
|
@Override
|
|
void apply(Builder builder) {
|
|
builder.expectedValues(new PlainA(101), new PlainA(101), new PlainA(101));
|
|
builder.creationTime(CreationTime.EAGER);
|
|
}
|
|
},
|
|
|
|
SCOPES_SINGLETON {
|
|
@Override
|
|
void configure(ScopedBindingBuilder sbb) {
|
|
sbb.in(Scopes.SINGLETON);
|
|
}
|
|
|
|
@Override
|
|
void apply(Builder builder) {
|
|
builder.expectedValues(new PlainA(201), new PlainA(201), new PlainA(201));
|
|
}
|
|
},
|
|
|
|
SINGLETON_DOT_CLASS {
|
|
@Override
|
|
void configure(ScopedBindingBuilder sbb) {
|
|
sbb.in(Singleton.class);
|
|
}
|
|
|
|
@Override
|
|
void apply(Builder builder) {
|
|
builder.expectedValues(new PlainA(201), new PlainA(201), new PlainA(201));
|
|
}
|
|
},
|
|
|
|
TWO_AT_A_TIME_SCOPED_DOT_CLASS {
|
|
@Override
|
|
void configure(ScopedBindingBuilder sbb) {
|
|
sbb.in(TwoAtATimeScoped.class);
|
|
}
|
|
|
|
@Override
|
|
void apply(Builder builder) {
|
|
builder.expectedValues(new PlainA(201), new PlainA(201), new PlainA(202), new PlainA(202));
|
|
}
|
|
},
|
|
|
|
TWO_AT_A_TIME_SCOPE {
|
|
@Override
|
|
void configure(ScopedBindingBuilder sbb) {
|
|
sbb.in(new TwoAtATimeScope());
|
|
}
|
|
|
|
@Override
|
|
void apply(Builder builder) {
|
|
builder.expectedValues(new PlainA(201), new PlainA(201), new PlainA(202), new PlainA(202));
|
|
}
|
|
};
|
|
|
|
abstract void configure(ScopedBindingBuilder sbb);
|
|
|
|
abstract void apply(Builder builder);
|
|
}
|
|
|
|
/** When Guice creates a value, directly or via a provider */
|
|
enum CreationTime {
|
|
NONE,
|
|
EAGER,
|
|
LAZY
|
|
}
|
|
|
|
public static class Builder {
|
|
private String name = "test";
|
|
private Key<?> key = Key.get(A.class);
|
|
private Class<? extends Injectable> injectsKey = InjectsA.class;
|
|
private List<Module> modules =
|
|
Lists.<Module>newArrayList(
|
|
new AbstractModule() {
|
|
@Override
|
|
protected void configure() {
|
|
bindScope(TwoAtATimeScoped.class, new TwoAtATimeScope());
|
|
}
|
|
});
|
|
private List<Object> expectedValues =
|
|
Lists.<Object>newArrayList(new PlainA(201), new PlainA(202), new PlainA(203));
|
|
private CreationTime creationTime = CreationTime.LAZY;
|
|
private String creationException;
|
|
private String configurationException;
|
|
|
|
public Builder module(Module module) {
|
|
this.modules.add(module);
|
|
return this;
|
|
}
|
|
|
|
public Builder creationTime(CreationTime creationTime) {
|
|
this.creationTime = creationTime;
|
|
return this;
|
|
}
|
|
|
|
public Builder name(String name) {
|
|
this.name = name;
|
|
return this;
|
|
}
|
|
|
|
public Builder key(Key<?> key, Class<? extends Injectable> injectsKey) {
|
|
this.key = key;
|
|
this.injectsKey = injectsKey;
|
|
return this;
|
|
}
|
|
|
|
private Builder creationException(String message, Object... args) {
|
|
this.creationException = String.format(message, args);
|
|
return this;
|
|
}
|
|
|
|
private Builder configurationException(String message, Object... args) {
|
|
configurationException = String.format(message, args);
|
|
return this;
|
|
}
|
|
|
|
private Builder scoper(Scoper scoper) {
|
|
name(name + " in " + scoper);
|
|
scoper.apply(this);
|
|
return this;
|
|
}
|
|
|
|
private <T> Builder expectedValues(T... values) {
|
|
this.expectedValues.clear();
|
|
Collections.addAll(this.expectedValues, values);
|
|
return this;
|
|
}
|
|
|
|
public void addToSuite(TestSuite suite) {
|
|
if (creationException != null) {
|
|
suite.addTest(new CreationExceptionTest(this));
|
|
|
|
} else if (configurationException != null) {
|
|
suite.addTest(new ConfigurationExceptionTest(this));
|
|
|
|
} else {
|
|
suite.addTest(new SuccessTest(this));
|
|
if (creationTime != CreationTime.NONE) {
|
|
suite.addTest(new UserExceptionsTest(this));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public static class SuccessTest extends TestCase {
|
|
final String name;
|
|
final Key<?> key;
|
|
final Class<? extends Injectable> injectsKey;
|
|
final ImmutableList<Module> modules;
|
|
final ImmutableList<Object> expectedValues;
|
|
|
|
public SuccessTest(Builder builder) {
|
|
super("test");
|
|
name = builder.name;
|
|
key = builder.key;
|
|
injectsKey = builder.injectsKey;
|
|
modules = ImmutableList.copyOf(builder.modules);
|
|
expectedValues = ImmutableList.copyOf(builder.expectedValues);
|
|
}
|
|
|
|
@Override
|
|
public String getName() {
|
|
return name;
|
|
}
|
|
|
|
Injector newInjector() {
|
|
nextId.set(101);
|
|
return Guice.createInjector(modules);
|
|
}
|
|
|
|
public void test() throws IllegalAccessException, InstantiationException {
|
|
Injector injector = newInjector();
|
|
nextId.set(201);
|
|
for (Object value : expectedValues) {
|
|
assertEquals(value, injector.getInstance(key));
|
|
}
|
|
|
|
Provider<?> provider = newInjector().getProvider(key);
|
|
nextId.set(201);
|
|
for (Object value : expectedValues) {
|
|
assertEquals(value, provider.get());
|
|
}
|
|
|
|
Provider<?> bindingProvider = newInjector().getBinding(key).getProvider();
|
|
nextId.set(201);
|
|
for (Object value : expectedValues) {
|
|
assertEquals(value, bindingProvider.get());
|
|
}
|
|
|
|
injector = newInjector();
|
|
nextId.set(201);
|
|
for (Object value : expectedValues) {
|
|
Injectable instance = injector.getInstance(injectsKey);
|
|
assertEquals(value, instance.value);
|
|
}
|
|
|
|
injector = newInjector();
|
|
nextId.set(201);
|
|
for (Object value : expectedValues) {
|
|
Injectable injectable = injectsKey.newInstance();
|
|
injector.injectMembers(injectable);
|
|
assertEquals(value, injectable.value);
|
|
}
|
|
|
|
Injector injector1 = newInjector();
|
|
nextId.set(201);
|
|
Injectable hasProvider = injector1.getInstance(injectsKey);
|
|
hasProvider.provider.get();
|
|
nextId.set(201);
|
|
for (Object value : expectedValues) {
|
|
assertEquals(value, hasProvider.provider.get());
|
|
}
|
|
}
|
|
}
|
|
|
|
public static class CreationExceptionTest extends TestCase {
|
|
final String name;
|
|
final Key<?> key;
|
|
final ImmutableList<Module> modules;
|
|
final String creationException;
|
|
|
|
public CreationExceptionTest(Builder builder) {
|
|
super("test");
|
|
name = builder.name;
|
|
key = builder.key;
|
|
modules = ImmutableList.copyOf(builder.modules);
|
|
creationException = builder.creationException;
|
|
}
|
|
|
|
@Override
|
|
public String getName() {
|
|
return "creation errors:" + name;
|
|
}
|
|
|
|
public void test() {
|
|
try {
|
|
Guice.createInjector(modules);
|
|
fail();
|
|
} catch (CreationException expected) {
|
|
assertContains(expected.getMessage(), creationException);
|
|
}
|
|
}
|
|
}
|
|
|
|
public static class ConfigurationExceptionTest extends TestCase {
|
|
final String name;
|
|
final Key<?> key;
|
|
final Class<? extends Injectable> injectsKey;
|
|
final ImmutableList<Module> modules;
|
|
final String configurationException;
|
|
|
|
public ConfigurationExceptionTest(Builder builder) {
|
|
super("test");
|
|
name = builder.name;
|
|
key = builder.key;
|
|
injectsKey = builder.injectsKey;
|
|
modules = ImmutableList.copyOf(builder.modules);
|
|
configurationException = builder.configurationException;
|
|
}
|
|
|
|
@Override
|
|
public String getName() {
|
|
return "provision errors:" + name;
|
|
}
|
|
|
|
Injector newInjector() {
|
|
return Guice.createInjector(modules);
|
|
}
|
|
|
|
public void test() throws IllegalAccessException, InstantiationException {
|
|
try {
|
|
newInjector().getProvider(key);
|
|
fail();
|
|
} catch (ConfigurationException expected) {
|
|
assertContains(expected.getMessage(), configurationException);
|
|
}
|
|
|
|
try {
|
|
newInjector().getBinding(key).getProvider();
|
|
fail();
|
|
} catch (ConfigurationException expected) {
|
|
assertContains(expected.getMessage(), configurationException);
|
|
}
|
|
|
|
try {
|
|
newInjector().getInstance(key);
|
|
fail();
|
|
} catch (ConfigurationException expected) {
|
|
assertContains(expected.getMessage(), configurationException);
|
|
}
|
|
|
|
try {
|
|
newInjector().getInstance(injectsKey);
|
|
fail();
|
|
} catch (ConfigurationException expected) {
|
|
assertContains(
|
|
expected.getMessage(),
|
|
configurationException,
|
|
injectsKey.getSimpleName() + ".inject",
|
|
injectsKey.getSimpleName() + ".inject",
|
|
"1 error");
|
|
}
|
|
|
|
try {
|
|
Injectable injectable = injectsKey.newInstance();
|
|
newInjector().injectMembers(injectable);
|
|
fail();
|
|
} catch (ConfigurationException expected) {
|
|
assertContains(
|
|
expected.getMessage(),
|
|
configurationException,
|
|
injectsKey.getSimpleName() + ".inject",
|
|
injectsKey.getSimpleName() + ".inject",
|
|
"1 error");
|
|
}
|
|
}
|
|
}
|
|
|
|
public static class UserExceptionsTest extends TestCase {
|
|
final String name;
|
|
final Key<?> key;
|
|
final Class<? extends Injectable> injectsKey;
|
|
final ImmutableList<Module> modules;
|
|
final ImmutableList<Object> expectedValues;
|
|
final CreationTime creationTime;
|
|
|
|
public UserExceptionsTest(Builder builder) {
|
|
super("test");
|
|
name = builder.name;
|
|
key = builder.key;
|
|
injectsKey = builder.injectsKey;
|
|
modules = ImmutableList.copyOf(builder.modules);
|
|
expectedValues = ImmutableList.copyOf(builder.expectedValues);
|
|
creationTime = builder.creationTime;
|
|
}
|
|
|
|
@Override
|
|
public String getName() {
|
|
return "provision errors:" + name;
|
|
}
|
|
|
|
Injector newInjector() {
|
|
return Guice.createInjector(modules);
|
|
}
|
|
|
|
public void test() throws IllegalAccessException, InstantiationException {
|
|
nextId.set(-1);
|
|
try {
|
|
newInjector();
|
|
assertEquals(CreationTime.LAZY, creationTime);
|
|
} catch (CreationException expected) {
|
|
assertEquals(CreationTime.EAGER, creationTime);
|
|
assertContains(expected.getMessage(), "Illegal value: -1");
|
|
return;
|
|
}
|
|
|
|
Provider<?> provider = newInjector().getProvider(key);
|
|
Provider<?> bindingProvider = newInjector().getBinding(key).getProvider();
|
|
|
|
nextId.set(-1);
|
|
try {
|
|
newInjector().getInstance(key);
|
|
fail();
|
|
} catch (ProvisionException expected) {
|
|
assertContains(expected.getMessage(), "Illegal value: -1");
|
|
}
|
|
|
|
nextId.set(-1);
|
|
try {
|
|
provider.get();
|
|
fail();
|
|
} catch (ProvisionException expected) {
|
|
assertContains(expected.getMessage(), "Illegal value: -1");
|
|
}
|
|
|
|
nextId.set(-1);
|
|
try {
|
|
bindingProvider.get();
|
|
fail();
|
|
} catch (ProvisionException expected) {
|
|
assertContains(expected.getMessage(), "Illegal value: -1");
|
|
}
|
|
|
|
try {
|
|
nextId.set(-1);
|
|
newInjector().getInstance(injectsKey);
|
|
fail("Expected ProvisionException");
|
|
} catch (ProvisionException expected) {
|
|
assertContains(expected.getMessage(), "Illegal value: -1", "for 1st parameter");
|
|
}
|
|
|
|
nextId.set(201);
|
|
Injectable injectable = injectsKey.newInstance();
|
|
try {
|
|
nextId.set(-1);
|
|
newInjector().injectMembers(injectable);
|
|
} catch (ProvisionException expected) {
|
|
assertContains(expected.getMessage(), "Illegal value: -1", "for 1st parameter");
|
|
}
|
|
|
|
nextId.set(201);
|
|
Injectable hasProvider = newInjector().getInstance(injectsKey);
|
|
hasProvider.provider.get();
|
|
try {
|
|
nextId.set(-1);
|
|
hasProvider.provider.get();
|
|
// TODO(lukes): insert fail() call here
|
|
} catch (ProvisionException expected) {
|
|
assertContains(expected.getMessage(), "Illegal value: -1");
|
|
}
|
|
}
|
|
}
|
|
|
|
/** negative to throw, 101... for eager singletons, 201... for everything else */
|
|
static final AtomicInteger nextId = new AtomicInteger();
|
|
|
|
@ProvidedBy(PlainAProvider.class)
|
|
interface AWithProvidedBy {}
|
|
|
|
static class InjectsAWithProvidedBy extends Injectable {
|
|
@Inject
|
|
public void inject(
|
|
AWithProvidedBy aWithProvidedBy, Provider<AWithProvidedBy> aWithProvidedByProvider) {
|
|
this.value = aWithProvidedBy;
|
|
this.provider = aWithProvidedByProvider;
|
|
}
|
|
}
|
|
|
|
static class InjectsAWithProvidedByNamedApple extends Injectable {
|
|
@Inject
|
|
public void inject(
|
|
@Named("apple") AWithProvidedBy aWithProvidedBy,
|
|
@Named("apple") Provider<AWithProvidedBy> aWithProvidedByProvider) {
|
|
this.value = aWithProvidedBy;
|
|
this.provider = aWithProvidedByProvider;
|
|
}
|
|
}
|
|
|
|
@ImplementedBy(PlainA.class)
|
|
interface AWithImplementedBy {}
|
|
|
|
static class InjectsAWithImplementedBy extends Injectable {
|
|
@Inject
|
|
public void inject(
|
|
AWithImplementedBy aWithImplementedBy,
|
|
Provider<AWithImplementedBy> aWithImplementedByProvider) {
|
|
this.value = aWithImplementedBy;
|
|
this.provider = aWithImplementedByProvider;
|
|
}
|
|
}
|
|
|
|
static class InjectsAWithImplementedByNamedApple extends Injectable {
|
|
@Inject
|
|
public void inject(
|
|
@Named("apple") AWithImplementedBy aWithImplementedBy,
|
|
@Named("apple") Provider<AWithImplementedBy> aWithImplementedByProvider) {
|
|
this.value = aWithImplementedBy;
|
|
this.provider = aWithImplementedByProvider;
|
|
}
|
|
}
|
|
|
|
interface A extends AWithProvidedBy, AWithImplementedBy {}
|
|
|
|
static class InjectsA extends Injectable {
|
|
@Inject
|
|
public void inject(A a, Provider<A> aProvider) {
|
|
this.value = a;
|
|
this.provider = aProvider;
|
|
}
|
|
}
|
|
|
|
static class PlainA implements A {
|
|
final int value;
|
|
|
|
PlainA() {
|
|
value = nextId.getAndIncrement();
|
|
if (value < 0) {
|
|
throw new RuntimeException("Illegal value: " + value);
|
|
}
|
|
}
|
|
|
|
PlainA(int value) {
|
|
this.value = value;
|
|
}
|
|
|
|
@Override
|
|
public boolean equals(Object obj) {
|
|
return obj instanceof PlainA && value == ((PlainA) obj).value;
|
|
}
|
|
|
|
@Override
|
|
public int hashCode() {
|
|
return value;
|
|
}
|
|
|
|
@Override
|
|
public String toString() {
|
|
return "PlainA#" + value;
|
|
}
|
|
}
|
|
|
|
static class PlainAProvider implements Provider<A> {
|
|
@Override
|
|
public A get() {
|
|
return new PlainA();
|
|
}
|
|
}
|
|
|
|
static class InjectsPlainA extends Injectable {
|
|
@Inject
|
|
public void inject(PlainA plainA, Provider<PlainA> plainAProvider) {
|
|
this.value = plainA;
|
|
this.provider = plainAProvider;
|
|
}
|
|
}
|
|
|
|
/** This scope hands out each value exactly twice */
|
|
static class TwoAtATimeScope implements Scope {
|
|
@Override
|
|
public <T> Provider<T> scope(Key<T> key, final Provider<T> unscoped) {
|
|
return new Provider<T>() {
|
|
T instance;
|
|
|
|
@Override
|
|
public T get() {
|
|
if (instance == null) {
|
|
instance = unscoped.get();
|
|
return instance;
|
|
} else {
|
|
T result = instance;
|
|
instance = null;
|
|
return result;
|
|
}
|
|
}
|
|
};
|
|
}
|
|
}
|
|
|
|
@Target({TYPE, METHOD})
|
|
@Retention(RUNTIME)
|
|
@ScopeAnnotation
|
|
public @interface TwoAtATimeScoped {}
|
|
|
|
@TwoAtATimeScoped
|
|
static class ScopedA extends PlainA {}
|
|
|
|
static class InjectsScopedA extends Injectable {
|
|
@Inject
|
|
public void inject(ScopedA scopedA, Provider<ScopedA> scopedAProvider) {
|
|
this.value = scopedA;
|
|
this.provider = scopedAProvider;
|
|
}
|
|
}
|
|
|
|
static class InjectsScopedANamedApple extends Injectable {
|
|
@Inject
|
|
public void inject(
|
|
@Named("apple") ScopedA scopedA, @Named("apple") Provider<ScopedA> scopedAProvider) {
|
|
this.value = scopedA;
|
|
this.provider = scopedAProvider;
|
|
}
|
|
}
|
|
|
|
static class Injectable {
|
|
Object value = new Object();
|
|
Provider<?> provider = Providers.of(new Object());
|
|
}
|
|
|
|
private static String shortNamed(Named named) {
|
|
return named.toString().replace("com.google.inject.name.", "");
|
|
}
|
|
}
|