Google Guice之作用域
2016-11-27 02:22
246 查看
默认情况下,Guice获取一个实例时,每次都会返回一个新的对象。这个行为可以通过scopes进行配置。Scopes允许你复用实例:
应用整个生命周期(@Singleton),
会话(@Session),
请求(@RequestScoped),
Guice还为Web应用提供了一种Servlet扩展作用域。并且在Guice还可以自定义范围。
Guice使用注解来标识作用域,将注解添加到某一类型的实现类上:
作用域也可以使用bind语句进行配置:
@Provides方法添加作用域注解:
如果在配置作用域时,使用注解与bind()语句存在冲突,那么以bind()中的配置为准。如果某一类型不想指定作用域则可以使用Scopes.NO_SCOPE.
在链接绑定中,作用域是应用于绑定源上,而不是应用了绑定目标上。假如我们有一个Appleess类实现了Bar和Grill接口,
下面的绑定配置就存在两个实例,一个用于Bar,另一个用于Grill:
这是因为作用域应用于绑定源(Bar,Grill),而不是绑定目标(Appless),如果要求只创建一个实例,则可以在Appless类上添加@Singleton注解,或者再添加一个绑定配置:
该绑定配置就使得两个.in(Singleton.class)语句变得多余了。in()语句不仅可以接收一个Scope注解,如RequestScope.class ,还可以接收Scope实例,如ServletScopes.REQUEST:
使用注解来配置作用域是更合适的,因为这样可以使Module对象在不类型中复用。
Guice有一种特殊的语法来定义需要立即创建的单例对象(Eager Singletons):
bind(TransactionLog.class).to(InMemoryTransactionLog.class).asEagerSingleton();
Eager Singletons对象保证终端使用者获得始终如一的体验,Lazy singletons则更适用于edit-compile-run开发周期。可以通过Stage枚举来选择使用哪一种策略。
*号表示只有已知类型才会立即创建单例对象,所谓已知类型为在Module中使用的类加上这些类的传递性依赖。
如何选择作用域:
如果一个对象是有状态的,它的状态就很明显了,每个应用使用则是@Singleton,每个请求使用则是@RequestScoped。
如果一个对象是无状态的并且创建的代价很小,就没有必要配置作用域了,Guice每次都创建一个新的对象。
单例模式在Java应用中很流行,但这样不能提供多个对象特别是在使用了依赖注入之后。虽然单例模式减少了对象的创建、使垃圾回收推后,但单例对象的初始化需要进行同步。单例对象最适用于:
a.有状态对象,如配置对象或者计数器
b.要花很大的代价去创建或者查找
c.捆绑了资源的对象,例如数据库连接池
当一个类加上了@Singleton或者@SessionScoped注解时,它必须是线程安全的。而且被注入到这个类中的类也必须是安全的,应该限制需要进行并发控制状态以最大限度地减少可变性。@RequestScoped对象没有必须是线程安全的,所以一个常见的错误是一个@Singleton或@SessionScoped对象依赖了一个@RequestScoped对象。
应用整个生命周期(@Singleton),
会话(@Session),
请求(@RequestScoped),
Guice还为Web应用提供了一种Servlet扩展作用域。并且在Guice还可以自定义范围。
Guice使用注解来标识作用域,将注解添加到某一类型的实现类上:
@Singleton public class InMemoryTransactionLog implements TransactionLog { /* everything here should be threadsafe! */ }
作用域也可以使用bind语句进行配置:
bind(TransactionLog.class).to(InMemoryTransactionLog.class).in(Singleton.class);
@Provides方法添加作用域注解:
@Provides @Singleton TransactionLog provideTransactionLog() { ... }
如果在配置作用域时,使用注解与bind()语句存在冲突,那么以bind()中的配置为准。如果某一类型不想指定作用域则可以使用Scopes.NO_SCOPE.
在链接绑定中,作用域是应用于绑定源上,而不是应用了绑定目标上。假如我们有一个Appleess类实现了Bar和Grill接口,
下面的绑定配置就存在两个实例,一个用于Bar,另一个用于Grill:
bind(Bar.class).to(Applebees.class).in(Singleton.class); bind(Grill.class).to(Applebees.class).in(Singleton.class);
这是因为作用域应用于绑定源(Bar,Grill),而不是绑定目标(Appless),如果要求只创建一个实例,则可以在Appless类上添加@Singleton注解,或者再添加一个绑定配置:
bind(Applebees.class).in(Singleton.class);
该绑定配置就使得两个.in(Singleton.class)语句变得多余了。in()语句不仅可以接收一个Scope注解,如RequestScope.class ,还可以接收Scope实例,如ServletScopes.REQUEST:
bind(UserPreferences.class).toProvider(UserPreferencesProvider.class).in(ServletScopes.REQUEST);
使用注解来配置作用域是更合适的,因为这样可以使Module对象在不类型中复用。
Guice有一种特殊的语法来定义需要立即创建的单例对象(Eager Singletons):
bind(TransactionLog.class).to(InMemoryTransactionLog.class).asEagerSingleton();
Eager Singletons对象保证终端使用者获得始终如一的体验,Lazy singletons则更适用于edit-compile-run开发周期。可以通过Stage枚举来选择使用哪一种策略。
PRODUCTION | DEVELOPMENT | |
.asEagerSingleton() | eager | eager |
.in(Singleton.class) | eager | lazy |
.in(Scopes.SINGLETON) | eager | lazy |
@Singleton | eager* | lazy |
如何选择作用域:
如果一个对象是有状态的,它的状态就很明显了,每个应用使用则是@Singleton,每个请求使用则是@RequestScoped。
如果一个对象是无状态的并且创建的代价很小,就没有必要配置作用域了,Guice每次都创建一个新的对象。
单例模式在Java应用中很流行,但这样不能提供多个对象特别是在使用了依赖注入之后。虽然单例模式减少了对象的创建、使垃圾回收推后,但单例对象的初始化需要进行同步。单例对象最适用于:
a.有状态对象,如配置对象或者计数器
b.要花很大的代价去创建或者查找
c.捆绑了资源的对象,例如数据库连接池
当一个类加上了@Singleton或者@SessionScoped注解时,它必须是线程安全的。而且被注入到这个类中的类也必须是安全的,应该限制需要进行并发控制状态以最大限度地减少可变性。@RequestScoped对象没有必须是线程安全的,所以一个常见的错误是一个@Singleton或@SessionScoped对象依赖了一个@RequestScoped对象。
相关文章推荐
- Google Guice之作用域
- Google Guice之作用域
- 网络安全中防火墙和IDS的作用
- Spring中的ContextLoaderListener作用
- css中!important的作用
- C/C++之回调函数---函数指针的作用
- iOS沙盒目录的查看,作用,特点
- (转) 安卓实现parcelable接口作用
- android 第三方库名字、作用、文章
- 雅思成绩越来越被重视 在申请美国名校条件中起举足轻重的作用
- mongodb中$的作用
- 什么是META标签?META标签在搜索引擎营销中有哪些作用?
- java内部类的作用分析(good)
- <context-param>与<init-param>的区别与作用
- 黑马程序员之sqlserver作用总结
- Android应用开发工程目录作用介绍
- Windows PE入门基础知识:Windows PE的作用、命名规则、启动方式、启动原理
- 【Linux】Linux系统各个目录的作用
- 深入理解javascript原型和闭包(12)——简介【作用域】
- 激活函数作用