Google Guice是依赖注解的DI容器,支持字段、方法和构造函数的注入依赖。
使用方法步骤为配置需要注入的字段、配置模板、使用Injector API获得实例。
一、 支持的注入方式
1、字段注入
最常见的方式,使用@Inject注解完成
@Inject
private XmlUserLoader loader;
2、构造函数注入
@Inject
public XmlUserServiceImpl(XmlUserLoader loader)
{
this.loader=loader;
}
3、setter方法注入
@Inject
public void setLoader(XmlUserLoader loader)
{
this.loader = loader;
}
二、 注入的API(配置模板)
Guice通过配置Module的方式来绑定关系。
public class ClientModule implements Module { public void configure(Binder binder) { binder.bind(UserService.class).to(XmlUserServiceImpl.class); } }
Binder中提供了很多绑定的API,这些API其实可以理解为配置文件。支持很多种类型的绑定 1、绑定一个具体的子类:
2、绑定一个实例:
binder.bind(UserService.class).toInstance(new XmlUserServiceImpl());
3、支持注解形式的绑定:
binder.bind(String.class).annotatedWith(Names.named("xmlUrl")).toInstance("/user.xml");
这样如果存在如下代码:
@Inject
@Named("xmlUrl")
private String xmlUrl;
那么这个字符串将会设置为"/user.xml"
当然也可以设置自定义的注解。但是个人认为Names这个注解已经基本满足要求了。
可以看一下com.google.inject.name.Names.named(String)方法,其实返回的是个注解,类继承了注解。
class NamedImpl implements com.google.inject.name.Named, Serializable { private final String value; //com.google.inject.name.Named是个注解类型 public NamedImpl(String value) { this.value = checkNotNull(value, "name"); }
自定义注解的示例:
@Retention(RUNTIME) @Target({ ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD }) @BindingAnnotation //这个必须要加上才行,否则报错 public @interface English { }
那么在Module中的使用如下:
public class Client { @Inject @English private MyService service; public void greeting() { System.out.println(service.greeting()); } public static void main(String[] args) { Module module = new Module() { public void configure(Binder binder) { binder.bind(MyService.class).annotatedWith(English.class).to(EnglishService.class); } }; Injector i = Guice.createInjector(module); Client client = i.getInstance(Client.class); client.greeting(); } }
4、provider形式的绑定
provider提供了更灵活的形式可以自定义创建对象的逻辑。框架提供了两种provider的形式。
A、实现provider接口,并绑定
修改上面示例如下:
final Provider<MyService> provider = new Provider<MyService>() { public MyService get() { // 用户的自定义创建逻辑 return new EnglishService(); } }; Module module = new Module() { public void configure(Binder binder) { binder.bind(MyService.class).annotatedWith(English.class).toProvider(provider); } };
B、通过@Provides在Module中定义方法
@Provides @Name("test") public MyService getMyService() { // 用户的自定义创建逻辑 return new EnglishService(); }
5、静态类注入
对静态字段类注入:
public void configure(Binder binder) { binder.bindConstant().annotatedWith(Names.named(("DataTimeUtils"))).to("yyyy-MM-dd"); binder.requestStaticInjection(DataTimeUtils.class); } @Inject @Named("DataTimeUtils") private static String dataFormat;
6、不明确的注入:
通过ImplementedBy注解指定需要使用的类
@ImplementedBy(EnglishService.class)
public interface MyService
{
String greeting();
}
三、 使用Injector API获取实例
Injector i = Guice.createInjector(new MyModule()); Client client = i.getInstance(Client.class); //直接获取实例 client.greeting();
Client client = new Client(); Injector i = Guice.createInjector(new MyModule()); i.injectMembers(client); //调用该API,填充字段 client.greeting();
binder.bind(UserService.class).to(XmlUserServiceImpl.class);