public static void main(String[] args) {
Injector injector = Guice.createInjector(new BindModule());
DogEgg dogEgg = injector.getInstance(DogEgg.class);
System.out.println(dogEgg.service);
}
interface Service {}
public static class DefaultService implements Service {}
public static class DogEgg {
// 告诉Guice,这里要注入东西,具体的注入规则从Module里找吧
@Inject
public Service service;
}
public static class BindModule implements Module {
@Override
public void configure(Binder binder) {
// 在注入的时候,遇到Service接口类型,全部注入成DefaultService实例
binder.bind(Service.class).to(DefaultService.class);
}
}
@BindingAnnotation
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.METHOD, ElementType.TYPE})
public @interface DefaultAnnotation{}
public static void main(String[] args) {
Injector injector = Guice.createInjector(new BindModule());
DogEgg dogEgg = injector.getInstance(DogEgg.class);
System.out.println(dogEgg.service);
System.out.println(dogEgg.service2);
}
interface Service {}
public static class DefaultService implements Service {}
public static class DefaultService2 implements Service {}
public static class DogEgg {
@Inject
@DefaultAnnotation
// 使用自定义注解标识该字段需要DefaultService实例
public Service service;
@Inject // 没有自定义注解,那就注入DefaultService2实例
public Service service2;
}
public static class BindModule implements Module {
@Override
public void configure(Binder binder) {
binder.bind(Service.class).annotatedWith(DefaultAnnotation.class).to(DefaultService.class).
in(Scopes.SINGLETON);
binder.bind(Service.class).to(DefaultService2.class);
}
}
public static void main(String[] args) {
Injector injector = Guice.createInjector(new BindModule());
DogEgg dogEgg = injector.getInstance(DogEgg.class);
System.out.println(dogEgg.service);
System.out.println(dogEgg.service2);
System.out.println(dogEgg.service3);
}
interface Service {}
public static class DefaultService implements Service {}
public static class DefaultService2 implements Service {}
public static class DogEgg {
@Inject
@Named("service1")
// 注意这里的@Named注解
public Service service;
@Inject
@Named("service2") // 注意这里的@Named注解
public Service service2;
@Inject
public Service service3; // 注意这里的没有@Named注解!!!
}
public static class BindModule implements Module {
@Override
public void configure(Binder binder) {
// 被@Named("service1")修饰的,给注入DefaultService实例
binder.bind(Service.class).annotatedWith(Names.named("service1"))
.to(DefaultService.class);
// 被@Named("service2")修饰的,给注入DefaultService2实例
binder.bind(Service.class).annotatedWith(Names.named("service2"))
.to(DefaultService2.class);
// 默认给注入DefaultService实例
binder.bind(Service.class).to(DefaultService.class);
}
}
DefaultService@fad74ee
DefaultService2@1a1d6a08
DefaultService@37d31475 // 和第一行的DefaultService实例不是一个?!
人家Spring可以配置单例还是原型,Guice也可以,在bind的时候指定一下就行,像上面那样不指定任何Scope的时候,每次注入时都会创建新实例!
public static class DogEgg {
@Inject
@Named("service1")
public Service service;
@Inject
@Named("service1")
public Service service5;
@Inject
@Named("service2")
public Service service2;
@Inject
public Service service3;
@Inject
public Service service4;
}
public static class BindModule implements Module {
@Override
public void configure(Binder binder) {
binder.bind(Service.class).annotatedWith(Names.named("service1"))
.to(DefaultService.class).in(Scopes.SINGLETON); // 这里指定了Scope
binder.bind(Service.class).annotatedWith(Names.named("service2"))
.to(DefaultService2.class);
binder.bind(Service.class).to(DefaultService.class).in(Scopes.SINGLETON); // 这里也指定了Scope
}
}
输出次序为service1、service5、service2、service3、service4如下:
DefaultService@ed9d034
DefaultService@ed9d034 // service1和service5是一个对象
DefaultService2@6121c9d6
DefaultService@87f383f
DefaultService@87f383f // service3和service4是一个对象,但是与service1和service2不相同
上面这波输出也告诉我们,Guice的单例是按照binding划分的。
如果要全局单例,可以使用@Singleton注解,代码如下:
@Singleton
// 这个注解告诉Guice,该实现全局单例
public static class DefaultService implements Service {}
public static class DefaultService2 implements Service {}
public static class DogEgg {
@Inject
@Named("service1")
public Service service;
@Inject
@Named("service1")
public Service service5;
@Inject
@Named("service2")
public Service service2;
@Inject
public Service service3;
@Inject
public Service service4;
}
public static class BindModule implements Module {
@Override
public void configure(Binder binder) {
binder.bind(Service.class).annotatedWith(Names.named("service1")).to(DefaultService.class);
// 这里没有再指定Scope
binder.bind(Service.class).annotatedWith(Names.named("service2")).to(DefaultService2.class);
binder.bind(Service.class).to(DefaultService.class); // 这里没有再指定Scope
}
}
这里的Singleton到底是懒汉模式还是饿汉模式呢?这个也是可以配置的,默认是懒汉模式,就是延迟加载!!!其实懒汉和饿汉模式在代码跑起来之后,没啥太大差别,毕竟该创建的都创建了。要是想详细理解的话,翻翻文档吧,这个不是特别重要。除了Singleton之外,还有Scope,例如ServletScopes.REQUEST,也去看文档吧,这个也不是特别重要。
除了上面介绍的字段注入,Guice还可以通过构造注入:
public static void main(String[] args) {
Injector injector = Guice.createInjector(new BindModule());
DogEgg dogEgg = injector.getInstance(DogEgg.class);
System.out.println(dogEgg.service);
System.out.println(dogEgg.service5);
System.out.println(dogEgg.service2);
System.out.println(dogEgg.service3);
System.out.println(dogEgg.service4);
}
interface Service {}
@Singleton
public static class DefaultService implements Service {
private String name;
private TestArg testArg;
public DefaultService(String name, TestArg testArg) { // 构造函数
this.name = name;
this.testArg = testArg;
}
public DefaultService() {} // 无参构造函数
@Override
public String toString() { // 这里专门加了一个hashCode(),用于区分是不是一个对象
return hashCode() +" DefaultService{" +
"name='" + name + '\'' +
", testArg=" + testArg +
'}';
}
}
public static class DefaultService2 implements Service {}
public static class DogEgg {
@Inject
@Named("service1")
public Service service;
@Inject
@Named("service1")
public Service service5;
@Inject
@Named("service2")
public Service service2;
@Inject
public Service service3;
@Inject
public Service service4;
}
public static class TestArg {
}
public static class BindModule implements Module {
@Override
public void configure(Binder binder) {
// 碰到@Named("service1")注解修饰的注入,继续走无参构造函数
binder.bind(Service.class).annotatedWith(Names.named("service1")).to(DefaultService.class);
binder.bind(Service.class).annotatedWith(Names.named("service2"))
.to(DefaultService2.class);
// binder.bind(Service.class).to(DefaultService.class);
// 这与下面走构造函数的binding冲突,Guice不知道该走哪个构造方法
try {
binder.bind(Service.class) // 没有@Named("service1")注解修饰的注入,走构造方法
.toConstructor(DefaultService.class
.getConstructor(String.class, TestArg.class));
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
}
}
网友评论