用一个对象工厂创建出来的对象,并且是单例的。
工厂类用枚举类,资源文件beans.properties中按照这样的格式写,key为所要创建的对象,value为类的全限定名称
#name=className
productDAO=dao.impl.ProductDAOImpl
productService=service.impl.ProductServiceImpl
先加载资源文件,用一个Map充当缓存(缓存中存在直接取出,没有再去创建对象). 用getBean方法来获取对象,两个参数分别为:所要创建对象的名称(与资源文件中的key对应)、对象所实现接口的类型(IXxx.class)
public enum BeanFactoy {
INSTANCE;
private static Properties p = new Properties();
private Map<String, Object> cache = new HashMap<>();
static {// 加载资源文件
InputStream inStream = Thread.currentThread().getContextClassLoader().getResourceAsStream("beans.properties");
try {
p.load(inStream);
} catch (IOException e) {
e.printStackTrace();
}
}
// 传递的参数等于资源文件中的key
@SuppressWarnings("unchecked")
public <T> T getBean(String beanName, Class<T> requiredType) {
// 判断缓存中是否存在指定名称的对象
Object current = cache.get(beanName);
if (current == null) {
String className = p.getProperty(beanName);// 得到类的权限顶名称
if (className != null) {
try {
Object obj = Class.forName(className).newInstance();
if (!requiredType.isInstance(obj)) {//判断obj是否为requireType的实例
throw new RuntimeException("类型不正确");
}
cache.put(beanName, obj);
} catch (Exception e) {
e.printStackTrace();
}
}
}
return (T) cache.get(beanName);
}
public static void main(String[] args) {
IProductDAO dao1 = BeanFactoy.INSTANCE.getBean("productDAO", IProductDAO.class);
IProductDAO dao2 = BeanFactoy.INSTANCE.getBean("productDAO", IProductDAO.class);
System.out.println(dao1);
System.out.println(dao2);// 相等. 说明是单例的
}
}