package org.dayatang.ioc.guice; import com.google.inject.*; import com.google.inject.name.Names; import org.dayatang.domain.InstanceProvider; import java.lang.annotation.Annotation; import java.util.HashSet; import java.util.Map; import java.util.Set; /** * 实例提供者接口的Google Guice实现。 * * @author yyang (<a href="mailto:gdyangyu@gmail.com">gdyangyu@gmail.com</a>) */ public class GuiceInstanceProvider implements InstanceProvider { private final Injector injector; /** * 以一批guice模块初始化guice实例提供者。 * * @param modules 一或多个guice模块 */ public GuiceInstanceProvider(Module... modules) { injector = Guice.createInjector(Stage.PRODUCTION, modules); } /** * 从Injector生成GuiceProvider * * @param injector */ public GuiceInstanceProvider(Injector injector) { this.injector = injector; } /** * 根据类型获取对象实例。返回的对象实例所属的类是T或它的实现类或子类。如果找不到该类型的实例则返回null。 * @param <T> 类型参数 * @param beanType 实例的类型 * @return 指定类型的实例。 */ @Override public <T> T getInstance(Class<T> beanType) { try { return injector.getInstance(beanType); } catch (com.google.inject.ConfigurationException e) { return null; } } /** * 根据类型和名称获取对象实例。如果找不到该类型的实例则返回null。 * 假如有两个类MyService1和MyService2都实现了接口Service,而在Guice模块中这样注册: * <pre> * binder.bind(Service.class).to(MyService1.class) * binder.bind(Service.class).annotatedWith(Names.named("service2")).to(MyService2.class) * </pre> * 那么getInstance(Service.class, "service2")将返回MyService2的实例。 * * @param <T> 类型参数 * @param beanName 实现类在容器中配置的名字 * @param beanType 实例的类型 * @return 指定类型的实例。 */ @Override public <T> T getInstance(Class<T> beanType, String beanName) { Key<T> key = Key.get(beanType, Names.named(beanName)); try { return injector.getInstance(key); } catch (com.google.inject.ConfigurationException e) { return null; } } /** * 根据类型和Annotation获取对象实例。如果找不到该类型的实例则返回null。 * 假如有两个类MyService1和MyService2都实现了接口Service,其中MyService2标记为@MyAnnotation, * 同时MyAnnotation标记为@BindingAnnotation @Retention(RetentionPolicy.RUNTIME) , * 而在Guice模块中这样注册: * binder.bind(Service.class).to(MyService1.class) * binder.bind(Service.class).annotatedWith(MyAnnotation.class).to(MyService2.class) * 那么getInstance(Service.class, MyAnnotation.class)将返回MyService2的实例。 * * @param <T> 类型参数 * @param beanType 实例的类型 * @param annotationType 实现类的annotation类型 * @return 指定类型的实例。 */ @Override public <T> T getInstance(Class<T> beanType, Class<? extends Annotation> annotationType) { Key<T> key = Key.get(beanType, annotationType); try { return injector.getInstance(key); } catch (com.google.inject.ConfigurationException e) { return null; } } @Override public <T> Set<T> getInstances(Class<T> beanType) { Map<Key<?>, Binding<?>> allBindings = injector.getAllBindings(); Set<T> results = new HashSet<T>(); for (Map.Entry<Key<?>, Binding<?>> entry : allBindings.entrySet()) { Key<?> key = entry.getKey(); System.out.println("Key: " + key.getTypeLiteral().getRawType()); if (beanType.isAssignableFrom(key.getTypeLiteral().getRawType())) { System.out.println("True"); results.add((T) entry.getValue().getProvider().get()); } } return results; } }