Guice是谷歌推出的一个轻量级依赖注入框架,帮助我们解决Java项目中的依赖注入问题。如果使用过Spring的话,会了解到依赖注入是个非常方便的功能。不过假如只想在项目中使用依赖注入,那么引入Spring未免大材小用了。这时候我们可以考虑使用Guice。本文参考了Guice官方文档,详细信息可以直接查看Guice文档。
基本使用
如果使用Maven的话,添加下面的依赖项。
1 | <dependency> |
快速开始
Guice的注入非常方便,不需要配置文件。
1 | // 被依赖的dao |
结果输出:
dao is saying
复制代码可以看到没有任何的xml配置,唯一需要做的,就是在需要注入的属性上打上@inject
。
使用 Guice.createInjector()
启动。通常需要尽早在程序中创建注入器。这样 Guice 能够帮助您创建大部分对象.
该demo中,并没有用到Module,也成功运行了,是因为之前没有涉及到接口,当只是依赖 确切的实现类 的时候,Guice会自动的找到需要注入的实现类
依赖绑定
链式绑定
我们在绑定依赖的时候不仅可以将父类和子类绑定,还可以将子类和更具体的子类绑定。下面的例子中,当我们需要TransactionLog
的时候,Guice
最后会为我们注入MySqlDatabaseTransactionLog
对象。
1 | public class BillingModule extends AbstractModule { |
注解绑定
当我们需要将多个同一类型的对象注入不同对象的时候,就需要使用注解区分这些依赖了。最简单的办法就是使用@Named注解进行区分。
首先需要在要注入的地方添加@Named注解。
1 | public class RealBillingService implements BillingService { |
然后在绑定中添加annotatedWith
方法指定@Named中
指定的名称。由于编译器无法检查字符串,所以Guice官方建议我们保守地使用这种方式。
1 | bind(CreditCardProcessor.class) |
如果希望使用类型安全的方式,可以自定义注解。
1 |
|
然后在需要注入的类上应用。
1 | public class RealBillingService implements BillingService { |
在配置类中,使用方法也和@Named类似。
1 | bind(CreditCardProcessor.class) |
实例绑定
有时候需要直接注入一个对象的实例,而不是从依赖关系中解析。如果我们要注入基本类型的话只能这么做。
1 | bind(String.class) |
@Provides
方法也可以应用@Named
和自定义注解,还可以注入其他依赖,Guice会在调用方法之前注入需要的对象。
1 |
|
Provider绑定
如果项目中存在多个比较复杂的对象需要构建,使用@Provides
方法会让配置类变得比较乱。我们可以使用Guice提供的Provider
接口将复杂的代码放到单独的类中。办法很简单,实现Provider<T>
接口的get
方法即可。在Provider
类中,我们可以使用@Inject
任意注入对象。
1 | public class DatabaseTransactionLogProvider implements Provider<TransactionLog> { |
在配置类中使用toProvider
方法绑定到Provider
上即可。
1 | public class BillingModule extends AbstractModule { |
作用域
默认情况下Guice会在每次注入的时候创建一个新对象。如果希望创建一个单例依赖的话,可以在实现类上应用@Singleton
注解。
1 |
|
或者也可以在配置类中指定。
1 | bind(TransactionLog.class) |
在@Provides
方法中也可以指定单例。
1 |
|
如果一个类型上存在多个冲突的作用域,Guice
会使用bind()
方法中指定的作用域。如果不想使用注解的作用域,可以在bind()
方法中将对象绑定为Scopes.NO_SCOPE
。
Guice和它的扩展提供了很多作用域,有单例Singleton
,Session作用域SessionScoped
,Request请求作用域RequestScoped
等等。我们可以根据需要选择合适的作用域。