package org.theonefx.wcframework.ioc; import java.util.LinkedHashSet; import java.util.Map; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import org.theonefx.wcframework.core.BeanDefinitionPostProcesser; import org.theonefx.wcframework.utils.Assert; class SingletonBeanFactory extends BeanDefinitionPostProcesser { /** * null的代替,为了解决ConcurrentHashMap不能存放null的问题 */ protected static final Object NULL_OBJECT = new Object(); /** * 缓存的单例对象map,用键值对的形式 */ private final Map<String, Object> singletonObjects = new ConcurrentHashMap<String, Object>(); /** * 出于效率考虑,增加一个set按顺序存放所有单例对象的id */ private final Set<String> registeredSingletons = new LinkedHashSet<String>(16); public void registerSingleton(String beanId, Object singletonObject) throws IllegalStateException { Assert.notNull(beanId, "'beanId' 不能为空"); synchronized (this.singletonObjects) { Object oldObject = this.singletonObjects.get(beanId); if (oldObject != null) { throw new IllegalStateException("无法使用 '" + beanId + "'注册对象 [" + singletonObject + "] : 对象已存在 [" + oldObject + "]"); } addSingleton(beanId, singletonObject); } } private void addSingleton(String beanName, Object singletonObject) { synchronized (this.singletonObjects) { this.singletonObjects.put(beanName, (singletonObject != null ? singletonObject : NULL_OBJECT)); this.registeredSingletons.add(beanName); } } public Object getSingleton(String beanName) { Object singletonObject = this.singletonObjects.get(beanName); return (singletonObject != NULL_OBJECT ? singletonObject : null); } public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) { Assert.notNull(beanName, "'beanName' 不能为空"); synchronized (this.singletonObjects) { Object singletonObject = this.singletonObjects.get(beanName); if (singletonObject == null) { if (log.isDebugEnabled()) { log.debug("创建共享的单例Bean:'" + beanName + "'"); } singletonObject = singletonFactory.getObject(); addSingleton(beanName, singletonObject); } return (singletonObject != NULL_OBJECT ? singletonObject : null); } } public boolean containsSingleton(String beanName) { return (this.singletonObjects.containsKey(beanName)); } protected final Object getSingletonObjectsMap() { return this.singletonObjects; } }