博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Guice系列之用户指南(十)
阅读量:5990 次
发布时间:2019-06-20

本文共 2395 字,大约阅读时间需要 7 分钟。

原文地址:https://code.google.com/p/google-guice/wiki/Scopes

Scopes:作用域。

默认情况下,Guice每次在调用时都会返回一个新的实例,这种行为是可以通过作用域配置的,作用域允许复用对象实例。在一个应用服务的生命周期中,对象可能是单例的(@Singleton),也可能是一个回话的(@SessionScoped),也可能是一个请求的(@RequestScoped)。Guice在web应用中也包含一个servlet扩展的作用域。自定义作用域可以在不同类型的应用中使用。

Applying Scopes

作用域使用有不用的方式,例如注解,

1
2
3
4
@Singleton
public
class
InMemoryTransactionLog
implements
TransactionLog {
  
/* everything here should be threadsafe! */
}

也可以配置在代码里,

1
bind(TransactionLog.
class
).to(InMemoryTransactionLog.
class
).in(Singleton.
class
);

也可以注解在@Provides方法处,

1
2
3
4
@Provides
@Singleton
  
TransactionLog provideTransactionLog() {
    
...
  
}

如果有些冲突的作用域同时在一个类型上或者代码里的bind()方法上配置,那么bind()的配置生效。如果一个类型你不想给它设置要作用域,那么就绑定Scopes.NO_SCOPE。

像链接绑定那样,作用域应用于绑定的父类型,而不是绑定目标实现类。设想我们有一个同时实现Bar接口和Grill接口的实现类Applebees,这就要求需要同时绑定的这两种类型,一种是类型Bar,另一种是Grill:

1
2
bind(Bar.
class
).to(Applebees.
class
).in(Singleton.
class
);
bind(Grill.
class
).to(Applebees.
class
).in(Singleton.
class
);

这是因为作用域应用于这个绑定的类型(Bar,Grill),而不是满足这个类型的实现类Applebees,为了允许只有一个实例,用一个注解@Singleton声明在父类型上,或者在代码里绑定。

1
bind(Applebees.
class
).in(Singleton.
class
);

这种绑定使得以上的其他两种.in(Singleton.class)语句不必要。这种in()语句还接受像RequestScoped.class或者是ServletScopes.REQUEST的注解:

1
2
3
bind(UserPreferences.
class
)
      
.toProvider(UserPreferencesProvider.
class
)
      
.in(ServletScopes.REQUEST);

这种注解是推荐优先的,因为它允许这个模块在不同的类型应用中复用,打个比方,一个被@RequestScoped注解的对象即能够在web应用的http请求中被使用,也可以在一个API服务器的rpc中被使用。

Eager Singletons

Eager Singletons(各种饥渴的单例):不是延迟的,是饿汉式的单例。
Guice有特殊的语法定义把单例为饿汉式的:

1
bind(TransactionLog.
class
).to(InMemoryTransactionLog.
class
).asEagerSingleton();

Guice有特殊的语法定义把单例为饥渴的:

饿汉式的单例可以很快揭示初始化问题,并确保最终用户获得一致的,直观的体验。懒汉式的单例保证了一个快速的编辑-完成-启动的开发周期,用这个Stage的枚举可以区分那种策略被使用:

PRODUCTION DEVELOPMENT
.asEagerSingleton() eager eager
.in(Singleton.class) eager lazy
.in(Scopes.SINGLETON) eager lazy
@Singleton eager* lazy

Guice会在已知类型的情况下创建饿汉式单例,这些类型都是在自己的模块,并加上这些类型递归依赖提到的类型。

Choosing a scope

选择一种作用域,如果一个对象是有状态的,那么这个作用域就明显了,每个应用都是@Singleton的,每个请求都是@RequestScoped等等。如果一个对象是没有状态的,并且创建开销是很小的,那么作用域就没有必要,就不用绑定作用域,Guice会按需要创建不同的实例。

许多单例在java应用中是很流行的但是但它们没有提供多大的价值,尤其是当涉及依赖注入。尽管单例可以节省对象创建开销,或者晚一点的垃圾回收,获取一个单例的句柄得到需要同步。单例是很有用的:

有状态的对象,例如配置或者计数
创建昂贵或者查找昂贵的对象
占用资源,如数据库连接池对象

Scopes and Concurrency

作用域和并发,类型被@Singleton和@SessionScoped注解的一定是线程安全的,任何被注入到这些类型的也一定是线程安全的,减少可变性来限制一些需要并发保护的状态。

@RequestScoped对象不需要线程安全,一个@Singleton和@SessionScoped对象来依赖@RequestScoped对象,这是一个错误常识。如果你需要一个对象在一个较窄的范围内,注入该对象的提供者。

转载地址:http://dnilx.baihongyu.com/

你可能感兴趣的文章
linux限制用户权限之lshel开通tcpdump权限
查看>>
PYTHON的函数对参数解析分析
查看>>
mfsmount
查看>>
Android 两点距离的计算方法
查看>>
Openwrt 交叉编译libxml2
查看>>
Redis(一)安装配置
查看>>
CentOS7使用yum安装nginx最新版本
查看>>
GCC X64
查看>>
Linux主机上通过iptables实现NAT功能
查看>>
覆写hashCode equal方法
查看>>
医疗信息化 医学信息 医院管理 资料下载
查看>>
Apache httpd 详解
查看>>
太赞了!书终于到了!
查看>>
16、OSPF配置实验之LSDB过载保护
查看>>
zabbix安装配置
查看>>
Android第三十八期 - 评价标签FlowLayout
查看>>
C++技巧: SFINAE
查看>>
查看mysql数据文件存放路径
查看>>
学习Qt的资源
查看>>
time模块
查看>>