package org.dayatang.domain;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.lang.annotation.Annotation;
import java.util.*;
/**
* <p>
* 实例工厂类,充当IoC容器的门面,通过它可以获得部署在IoC容器中的Bean的实例。 InstanceFactory向客户代码隐藏了IoC
* 工厂的具体实现。在后台,它通过InstanceProvider策略接口,允许选择不同的IoC工厂,例如Spring, Google Guice和
* TapestryIoC等等。
* <p>
* IoC工厂应该在应用程序启动时装配好,也就是把初始化好的InstanceProvider实现类提供给InstanceFactory。对于web应用
* 来说,最佳的初始化方式是创建一个Servlet过滤器或监听器,并部署到web.xml里面;对普通java应用程序来说,最佳的初始化
* 位置是在main()函数里面;对于单元测试,最佳的初始化位置是@BeforeClass或@Before标注的方法内部。<br>
* <p>
* InstanceFactor顺序通过三种途径获取Bean实例。(1)如果已经给InstanceFactory设置了InstanceProvider,那么就通过后者
* 查找Bean;(2)如果没有设置InstanceProvider,或者通过InstanceProvider无法找到Bean,就通过JDK6的ServiceLoader查找(通
* 过在类路径或jar中的/META-INF/services/a.b.c.Abc文件中设定内容为x.y.z.Xyz,就表明类型a.b.c.Abc将通过类x.y.z.Xyz
* 的实例提供);(3)如果仍然没找到Bean实例,那么将返回那些通过bind()方法设置的Bean实例。(4)如果最终仍然找不到,就抛出
* IocInstanceNotFoundException异常。
*
* @author yyang (<a href="mailto:gdyangyu@gmail.com">gdyangyu@gmail.com</a>)
*/
public class InstanceFactory {
private static final Logger LOGGER = LoggerFactory.getLogger(InstanceFactory.class);
/**
* 以下部分仅用于提供代码测试功能,产品代码不要用
*/
private static final Map<Object, Object> instances = new HashMap<Object, Object>();
//实例提供者,代表真正的IoC容器
private static InstanceProvider instanceProvider;
private static InstanceLocatorFactory instanceLocatorFactory = ServiceLoader.load(InstanceLocatorFactory.class).iterator().next();
private static List<InstanceLocator> instanceLocators = new ArrayList<InstanceLocator>();
static {
instanceLocators.add(instanceLocatorFactory.createByServiceLoader());
instanceLocators.add(instanceLocatorFactory.create(instances));
}
private InstanceFactory() {
}
/**
* 设置实例提供者。
*
* @param provider 一个实例提供者的实例。
*/
public static void setInstanceProvider(InstanceProvider provider) {
instanceProvider = provider;
if (instanceProvider == null) {
return;
}
instanceLocators.add(0, instanceLocatorFactory.create(instanceProvider));
}
/**
* 根据类型获取对象实例。返回的对象实例所属的类是T或它的实现类或子类。如果找不到该类型的实例则抛出异常。
*
* @param <T> 对象的类型
* @param beanType 对象所属的类型
* @return 类型为T的对象实例
*/
@SuppressWarnings("unchecked")
public static <T> T getInstance(Class<T> beanType) {
for (InstanceLocator locator : instanceLocators) {
T result = locator.getInstance(beanType);
if (result != null) {
return result;
}
}
throw new IocInstanceNotFoundException("There's not bean of type '" + beanType + "' exists in IoC container!");
}
/**
* 根据类型和名称获取对象实例。返回的对象实例所属的类是T或它的实现类或子类。不同的IoC容器用不同的方式解释beanName。
* 具体的解释方式请参见各种InstanceProvider实现类的Javadoc。 如果找不到该类型的实例则抛出异常。
*
* @param <T> 类型参数
* @param beanName bean的名称
* @param beanType 实例的类型
* @return 指定类型的实例。
*/
@SuppressWarnings("unchecked")
public static <T> T getInstance(Class<T> beanType, String beanName) {
for (InstanceLocator locator : instanceLocators) {
T result = locator.getInstance(beanType, beanName);
if (result != null) {
return result;
}
}
throw new IocInstanceNotFoundException("There's not bean of type '" + beanType + "' exists in IoC container!");
}
/**
* 根据类型和Annotation获取对象实例。返回的对象实例所属的类是T或它的实现类或子类。不同的IoC容器用不同的方式解释annotation。
* 具体的解释方式请参见各种InstanceProvider实现类的Javadoc。 如果找不到该类型的实例则抛出异常。
*
* @param <T> 类型参数
* @param beanType 实例的类型
* @param annotationType 实现类的annotation类型
* @return 指定类型的实例。
*/
public static <T> T getInstance(Class<T> beanType, Class<? extends Annotation> annotationType) {
for (InstanceLocator locator : instanceLocators) {
T result = locator.getInstance(beanType, annotationType);
if (result != null) {
return result;
}
}
throw new IocInstanceNotFoundException("There's not bean '"
+ annotationType + "' of type '" + beanType + "' exists in IoC container!");
}
/**
* 将服务绑定到具体实例
*
* @param <T> Bean实例的类型
* @param serviceInterface 注册类型
* @param serviceImplementation 对象实例
*/
public static <T> void bind(Class<T> serviceInterface, T serviceImplementation) {
instances.put(serviceInterface, serviceImplementation);
}
/**
* 将服务绑定到具体实例并指定名字
*
* @param <T> Bean实例的类型
* @param serviceInterface 注册类型
* @param serviceImplementation 对象实例
* @param beanName 实例名称
*/
public static <T> void bind(Class<T> serviceInterface, T serviceImplementation, String beanName) {
instances.put(toName(serviceInterface, beanName), serviceImplementation);
}
/**
* 删除缓存的bean实例
*/
public static void clear() {
instances.clear();
}
/**
* 将服务绑定到具体实例并指定关联的Annotation
*
* @param <T> Bean实例的类型
* @param serviceInterface 注册类型
* @param serviceImplementation 对象实例
* @param annotationType 标注类型
*/
public static <T> void bind(Class<T> serviceInterface, T serviceImplementation, Class<? extends Annotation> annotationType) {
instances.put(toName(serviceInterface, annotationType), serviceImplementation);
}
private static String toName(Class<?> beanType, String beanName) {
return beanType.getName() + ":" + beanName;
}
private static String toName(Class<?> beanType, Class<? extends Annotation> annotationType) {
return beanType.getName() + ":" + annotationType.getName();
}
}